Main Page   Namespace List   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

connection.cpp

Go to the documentation of this file.
00001 
00009 #include "sysconfig.h"
00010 #include "connection.h"
00011 
00012 
00017 //##ModelId=3ED44BF10253
00018 Connection::Connection(SOCKET sock)
00019         : mSock(sock), mpPendingInput(NULL), mpPendingOutput(NULL),
00020 mDisconnectable(false) {}
00021 
00025 //##ModelId=3ED44BF10255
00026 Connection::~Connection() {
00027     delete[] mpPendingOutput;
00028     delete[] mpPendingInput;
00029 }
00030 
00034 //##ModelId=3ED44BF1025E
00035 Connection::Connection(const Connection& r_conn)
00036         : mDisconnectable(r_conn.mDisconnectable), mSock(r_conn.mSock),
00037 mpPendingInput(NULL), mpPendingOutput(NULL) {
00038     mInBuffer = r_conn.mInBuffer;
00039     mOutBuffer = r_conn.mOutBuffer;
00040     if (r_conn.mpPendingInput) {
00041         mpPendingInput = new char[strlen(r_conn.mpPendingInput) + 1];
00042         strcpy(mpPendingInput, r_conn.mpPendingInput);
00043     }
00044     if (r_conn.mpPendingOutput) {
00045         mpPendingOutput = new char[strlen(r_conn.mpPendingOutput) + 1];
00046         strcpy(mpPendingOutput, r_conn.mpPendingOutput);
00047     }
00048 }
00049 
00053 //##ModelId=3ED44BF10288
00054 Connection & Connection::operator=(const Connection& r_conn) {
00055     if (this == &r_conn)
00056         return * this;
00057     mInBuffer = r_conn.mInBuffer;
00058     mOutBuffer = r_conn.mOutBuffer;
00059     if (r_conn.mpPendingInput) {
00060         mpPendingInput = new char[strlen(r_conn.mpPendingInput) + 1];
00061         strcpy(mpPendingInput, r_conn.mpPendingInput);
00062     }
00063     if (r_conn.mpPendingOutput) {
00064         mpPendingOutput = new char[strlen(r_conn.mpPendingOutput) + 1];
00065         strcpy(mpPendingOutput, r_conn.mpPendingOutput);
00066     }
00067     return *this;
00068 }
00069 
00086 //##ModelId=3ED44BF10260
00087 void Connection::HandleInput() {
00088     string strin;
00089     char inbuf[4096];
00090     // If there was input leftover from the last call to HandleInput
00091     // prepend it to the input string and clear it.
00092     if (mpPendingInput) {
00093         strin.append(mpPendingInput);
00094         delete[] mpPendingInput;
00095         mpPendingInput = NULL;
00096     }
00097     // Loop to gather all socket input in 4K chunks.
00098     while (true) {
00099         int nbytes = recv (mSock, inbuf, 4096, 0);
00100         if (nbytes == 0) {
00101             // Connection is scheduled for disconnection, and we'll exit
00102             mDisconnectable = true;
00103             return ;
00104         } else if (nbytes == SOCKET_ERROR) {
00105             int err = WSAGetLastError ();
00106             if (err == WSAEWOULDBLOCK) {
00107                 // Indicates no more input can be squeezed from this socket.
00108                 // Let's bust this loop
00109                 break;
00110             } else {
00111                 // We have a serious error
00112                 // Connection is scheduled for disconnection, and we'll exit
00113                 cout << "Error-Connection(recv):" << err << " on " << mSock << endl;
00114                 mDisconnectable = true;
00115                 return ;
00116             }
00117         }
00118         // Append everything read to our string.
00119         inbuf[nbytes] = '\0';
00120         strin.append(inbuf);
00121     }
00122     // Loop to parse all input into lines for our buffer
00123     while (true) {
00124         int pos = strin.find("\r\n");
00125         if (pos != (int)strin.npos) {
00126             // A line was found; save it to buffer and remove from input string
00127             mInBuffer.push_back(strin.substr(0, pos));
00128             strin.erase(0, pos + 2);
00129         } else {
00130             // No       more complete lines found
00131             if (!strin.empty()) {
00132                 // Save leftovers into pending input array
00133                 mpPendingInput = new char[strin.size() + 1];
00134                 strcpy(mpPendingInput, strin.c_str());
00135             }
00136             break;
00137         }
00138     }
00139 }
00140 
00153 //##ModelId=3ED44BF10268
00154 void Connection::HandleOutput() {
00155     string strout;
00156     // If there is output left to be sent from last time append
00157     // it to our output string
00158     if (mpPendingOutput) {
00159         strout.append(mpPendingOutput);
00160         delete[] mpPendingOutput;
00161         mpPendingOutput = NULL;
00162     }
00163     // If there is any output waiting in line buffer append the first line
00164     if (!mOutBuffer.empty()) {
00165         strout.append(mOutBuffer.front());
00166         mOutBuffer.pop_front();
00167     }
00168     // Loop until our output string is empty
00169     while (!strout.empty()) {
00170         const char * pstr = strout.c_str();
00171         while (pstr) {  // Loop until we have written this string
00172             int nbytes = send (mSock, pstr, strlen(pstr), 0);
00173             if (nbytes == SOCKET_ERROR) {
00174                 int err = WSAGetLastError ();
00175                 if (err == WSAEWOULDBLOCK) {
00176                     // socket will block - save unwritten output in pending array
00177                     // and leave
00178                     mpPendingOutput = new char[strlen(pstr) + 1];
00179                     strcpy(mpPendingOutput, pstr);
00180                     return ;
00181                 }
00182                 // severe error set socket as disconnectable and leave
00183                 cout << "Error-Connection(recv):" << err << " on " << mSock << endl;
00184                 mDisconnectable = true;
00185                 return ;
00186             } else if (nbytes < (int)strlen(pstr)) {
00187                 pstr += nbytes;
00188             } else {
00189                 pstr = NULL;
00190             }
00191         }
00192         strout.erase();
00193         // fetch next line in buffer if not empty
00194         if (!mOutBuffer.empty()) {
00195             strout.append(mOutBuffer.front());
00196             mOutBuffer.pop_front();
00197         }
00198     }
00199 }
00200 
00204 //##ModelId=3ED44BF10272
00205 void Connection::Disconnect() {
00206     char inbuf[4096];
00207     bool done = false;
00208     shutdown(mSock, SD_SEND);
00209     while (!done) {
00210         int nbytes = recv (mSock, inbuf, 4096, 0);
00211         if (!nbytes || nbytes == SOCKET_ERROR)
00212             done = true;
00213     }
00214     closesocket(mSock);
00215 }
00216 
00222 //##ModelId=3ED44BF10274
00223 void Connection::SendMsg(const string& r_msg) {
00224     mOutBuffer.push_back(r_msg);
00225 }
00226 
00232 //##ModelId=3ED44BF1027D
00233 string* Connection::ReadMsg() {
00234     if (!mInBuffer.empty()) {
00235         string msg = mInBuffer.front();
00236         mInBuffer.pop_front();
00237         return new string(msg);
00238     }
00239     return NULL;
00240 }
00241 
00250 //##ModelId=3ED44BF1026A
00251 bool Connection::CanBeDisconnected() {
00252     return mDisconnectable;
00253 }
00254 
00260 //##ModelId=3ED44BF10286
00261 SOCKET Connection::GetSocket() {
00262     return mSock;
00263 }

Generated on Mon Mar 29 22:38:41 2004 for Paradigm by doxygen1.2.17