public void Run()
{
Logger.Write (LogLevel.Notice,
Strings.Connection_BeginningRun);
if (socket == null) {
Logger.Write (LogLevel.Notice, Strings.Connection_NoSocketInRun);
return;
}
do {
Record record;
try {
record = new Record (socket,
receive_buffer);
} catch (System.Net.Sockets.SocketException) {
StopRun (Strings.Connection_RecordNotReceived);
Stop ();
break;
}
Request request = GetRequest (record.RequestID);
switch (record.Type) {
// Creates a new request.
case RecordType.BeginRequest:
// If a request with the given ID
// already exists, there's a bug in the
// client. Abort.
if (request != null) {
StopRun (Strings.Connection_RequestAlreadyExists);
break;
}
// If there are unfinished requests
// and multiplexing is disabled, inform
// the client and don't begin the
// request.
if (!server.MultiplexConnections &&
UnfinishedRequests) {
EndRequest (record.RequestID, 0,
ProtocolStatus.CantMultiplexConnections);
break;
}
// If the maximum number of requests is
// reached, inform the client and don't
// begin the request.
if (!server.CanRequest) {
EndRequest (record.RequestID, 0,
ProtocolStatus.Overloaded);
break;
}
BeginRequestBody body = new BeginRequestBody
(record);
// If the role is "Responder", and it is
// supported, create a ResponderRequest.
if (body.Role == Role.Responder &&
server.SupportsResponder)
request = new ResponderRequest
(record.RequestID, this);
// If the request is null, the role is
// not supported. Inform the client and
// don't begin the request.
if (request == null) {
Logger.Write (LogLevel.Warning,
Strings.Connection_RoleNotSupported,
body.Role);
EndRequest (record.RequestID, 0,
ProtocolStatus.UnknownRole);
break;
}
lock (request_lock) {
requests.Add (request);
}
keep_alive = (body.Flags &
BeginRequestFlags.KeepAlive) != 0;
break;
// Gets server values.
case RecordType.GetValues:
byte [] response_data;
// Look up the data from the server.
try {
IDictionary<string,string> pairs_in = NameValuePair.FromData (record.GetBody ());
IDictionary<string,string> pairs_out = server.GetValues (pairs_in.Keys);
response_data = NameValuePair.GetData (pairs_out);
} catch {
response_data = new byte [0];
}
SendRecord (RecordType.GetValuesResult,
record.RequestID, response_data);
break;
// Sends params to the request.
case RecordType.Params:
if (request == null) {
StopRun (Strings.Connection_RequestDoesNotExist,
record.RequestID);
break;
}
request.AddParameterData (record.GetBody ());
break;
// Sends standard input to the request.
case RecordType.StandardInput:
if (request == null) {
StopRun (Strings.Connection_RequestDoesNotExist,
record.RequestID);
break;
}
request.AddInputData (record);
break;
// Sends file data to the request.
case RecordType.Data:
if (request == null) {
StopRun (Strings.Connection_RequestDoesNotExist,
record.RequestID);
break;
}
request.AddFileData (record);
break;
// Aborts a request when the server aborts.
case RecordType.AbortRequest:
if (request == null)
break;
request.Abort (
Strings.Connection_AbortRecordReceived);
break;
// Informs the client that the record type is
// unknown.
default:
Logger.Write (LogLevel.Warning,
Strings.Connection_UnknownRecordType,
record.Type);
SendRecord (RecordType.UnknownType,
record.RequestID,
new UnknownTypeBody (
record.Type).GetData ());
break;
}
}
while (!stop && (UnfinishedRequests || keep_alive));
if (requests.Count == 0) {
lock (connection_teardown_lock) {
try {
if (socket != null)
socket.Close ();
} catch (System.Net.Sockets.SocketException e) {
// Ignore: "The descriptor is not a socket"
// error from UnmanagedSocket.Close
if (e.ErrorCode != 10038)
throw; // Rethrow other errors
} finally {
socket = null;
}
if (!stop)
server.EndConnection (this);
if (receive_buffer != null && send_buffer != null) {
server.ReleaseBuffers (receive_buffer, send_buffer);
receive_buffer = null;
send_buffer = null;
}
}
}
Logger.Write (LogLevel.Notice,
Strings.Connection_EndingRun);
}