00001
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include <string.h>
00037 #include <ctype.h>
00038 #include "ctl/ctldef.h"
00039 #include "ctl/pool.h"
00040 #include "ctl/ctlnew.h"
00041 #include "ctl/socket.h"
00042
00043
00044 #ifdef WIN32
00045 #include <ws2tcpip.h>
00046 #define EWOULDBLOCK WSAEWOULDBLOCK
00047 #define SHUT_RDRW SD_BOTH
00048 #define SocketError() WSAGetLastError()
00049 #define SocketSetError(e) WSASetLastError(e)
00050 #else
00051 #define INVALID_SOCKET -1
00052 #define SOCKET_ERROR -1
00053 #define closesocket close
00054 #define SocketError() errno
00055 #define SocketSetError(e) (errno = (e))
00056 #include <fcntl.h>
00057 #include <stropts.h>
00058 #endif
00059
00060
00061 static const uint32 GUARD_BYTES = 0xDEADBAB4;
00062
00063
00064
00065
00066 ctl_fp_decl( Socket, MAX_SOCKETS, SocketPool );
00067 static SocketPool* sockPool;
00068
00069
00070
00071
00072 dll_autolist(Socket,active, socksActive);
00073 static void Socket_Free( Socket* sock );
00074
00075
00076
00077 static size_t cSockActive = 0;
00078 static size_t cSockFree = MAX_SOCKETS;
00079
00080
00081
00082 ppWindows(static WSADATA wsaData;)
00083 static const size_t cSockTotal = MAX_SOCKETS;
00084 static size_t sockInSize;
00085 static size_t sockOutSize;
00086 static size_t sockHeapSize;
00087 static size_t sockBufferSize;
00088 static size_t sockOffsetOut;
00089 static size_t sockOffsetEnd;
00090 static size_t bufferSize;
00091 static uint8* bufferSpace = NULL;
00092 static size_t sockUserSize;
00093 static size_t userSize;
00094 static uint8* userSpace = NULL;
00095 #define SOCK_INPUT_DEFAULTPTR(index) (bufferSpace + (index * sockBufferSize))
00096 #define SOCK_OUTPUT_DEFAULTPTR(index) ((bufferSpace + (index * sockBufferSize)) + sockOffsetOut)
00097 #define SOCK_HEAP_DEFAULTPTR(index) (userSpace + (index * sockUserSize))
00098
00104 uint32 SocketID( const Socket* sock )
00105 {
00106 assertobjconst(sock);
00107 if( !ctl_fp_valid(SocketPool, sockPool, sock ) )
00108 return 0;
00109 if( Socket_ShouldIgnore(sock) )
00110 return 0;
00111 return sock->id;
00112 }
00113
00119 Socket* SocketLut( uint32 id )
00120 {
00121 Socket* sock = ctl_fp_lut(SocketPool, sockPool, id&0xffff );
00122 if( NULL == sock )
00123 return NULL;
00124 if( sock->id != id )
00125 return NULL;
00126 if( Socket_ShouldIgnore(sock) )
00127 return NULL;
00128 return sock;
00129 }
00130
00138 Socket* SocketFind( const char* label )
00139 {
00140 assertconst(label,1);
00141 {
00142 socket_foreach( sock )
00143 {
00144 assertobjptr(sock);
00145 if( !Socket_ShouldIgnore(sock) && !strcmp(sock->label,label) )
00146 {
00147 return sock;
00148 }
00149 }
00150 }
00151 return NULL;
00152 }
00153
00154
00155 static void Socket_DefaultReceived( Socket* sock, ctl_serial* packet )
00156 {
00157 assertobjptr(sock);
00158 assertobjptr(packet);
00159 }
00160
00161 static void Socket_DefaultCallback( Socket* sock )
00162 {
00163 assertobjptr(sock);
00164 }
00165
00166 static NewSocketCallback login_callback = Socket_DefaultCallback;
00167 static NewSocketCallback user_callback = Socket_DefaultCallback;
00168
00174 NewSocketCallback SocketsSetLogin( NewSocketCallback callback )
00175 {
00176 NewSocketCallback cb_old = login_callback;
00177 login_callback = NULL == callback ? Socket_DefaultCallback : callback;
00178 assertcodeptr(login_callback);
00179 return cb_old;
00180 }
00181
00187 NewSocketCallback SocketsSetUser( NewSocketCallback callback )
00188 {
00189 NewSocketCallback cb_old = user_callback;
00190 user_callback = NULL == callback ? Socket_DefaultCallback : callback;
00191 assertcodeptr(user_callback);
00192 return cb_old;
00193 }
00194
00195
00205 bool SocketsInit( size_t input, size_t output, size_t heap )
00206 {
00207 trace(("SocketsInit()\n"));
00208 sockInSize = input;
00209 sockOutSize = output;
00210 sockHeapSize = heap;
00211 sockBufferSize = (sockInSize + sockOutSize + (2*sizeof(uint32)));
00212 sockOffsetOut = sockInSize + sizeof(uint32);
00213 sockOffsetEnd = sockOffsetOut + sizeof(uint32);
00214 bufferSize = MAX_SOCKETS * sockBufferSize;
00215 sockUserSize = sockHeapSize + sizeof(uint32);
00216 userSize = MAX_SOCKETS * sockUserSize;
00217
00218 #ifdef WIN32
00219 {
00220
00221 int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
00222 if (iResult != 0)
00223 {
00224 SocketsLogLastError( LOG_ERROR, "WSAStartup failed: %d\n", iResult );
00225 return false;
00226 }
00227 LOG( LOG_STARTUP,"%s - %s\n", wsaData.szDescription, wsaData.szSystemStatus );
00228 }
00229 #endif
00230
00231
00232 ctl_alloctype(sockPool,SocketPool);
00233 ctl_fp_init( SocketPool, sockPool );
00234
00235
00236
00237
00238 ctl_malloc( bufferSpace, bufferSize );
00239 ctl_malloc( userSpace, userSize );
00240 return true;
00241 }
00242
00246 void SocketsShutdown(void)
00247 {
00248 trace(("SocketsShutdown()\n"));
00249 {
00250
00251 socket_foreach( sock )
00252 {
00253 assertobjptr(sock);
00254 Socket_Close(sock);
00255 }
00256 }
00257 {
00258
00259 socket_foreach_deletable( sock )
00260 {
00261 assertobjptr(sock);
00262 Socket_Free(sock);
00263 }
00264 }
00265
00266 ctl_free(sockPool);
00267
00268 ctl_free(bufferSpace);
00269
00270 ctl_free(userSpace);
00271
00272 dll_initlist(Socket,active, socksActive);
00273
00274 assert( 0 == cSockActive );
00275 assert( MAX_SOCKETS == cSockFree );
00276 cSockActive = 0;
00277 cSockFree = MAX_SOCKETS;
00278 #ifdef WIN32
00279 WSACleanup();
00280 #endif
00281 }
00282
00288 bool SocketsCycle( unsigned ms )
00289 {
00290 mstime tick = ctl_mstime();
00291 #ifdef WIN32
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 Sleep( 1 );
00308
00309
00310 {
00311 socket_foreach_deletable( sock )
00312 {
00313 assertobjptr(sock);
00314 if( tick - sock->lastmsg > sock->timeout )
00315 {
00316 SocketLogIP(sock,LOG_INFO,"Timed out:");
00317 Socket_Close(sock);
00318 }
00319 if( stUninitialized == sock->type )
00320 {
00321 Socket_Free(sock);
00322 }
00323 }
00324 }
00325 #else
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 static fd_set fdreads;
00336 static fd_set fdwrites;
00337
00338 FD_ZERO(&fdreads);
00339 FD_ZERO(&fdwrites);
00340 {
00341 int nfds = -1;
00342 socket_foreach_deletable( sock )
00343 {
00344 assertobjptr(sock);
00345 if( stUninitialized != sock->type && INVALID_SOCKET != sock->socket )
00346 {
00347 if( tick - sock->lastmsg > sock->timeout )
00348 {
00349 SocketLogIP(sock,LOG_INFO,"Timed out:");
00350 Socket_Close(sock);
00351 }
00352 else
00353 {
00354 SOCKET sockCurr = sock->socket;
00355 if( stSendingFinal != sock->type )
00356 {
00357
00358 FD_SET( sockCurr, &fdreads );
00359 }
00360 if( !RingBuff_IsEmpty(&sock->output) )
00361 {
00362 FD_SET( sockCurr, &fdwrites );
00363 }
00364 if( sock->socket > nfds )
00365 {
00366 nfds = sockCurr;
00367 }
00368 }
00369 }
00370 if( stUninitialized == sock->type )
00371 {
00372 Socket_Free(sock);
00373 }
00374 }
00375
00376 {
00377 struct timeval timeout = { ms/1000, (ms%1000)*1000 };
00378 nfds = select( 1+nfds, &fdreads, &fdwrites, NULL, 0 == ms ? NULL : &timeout );
00379 }
00380 if( 0 == nfds )
00381 {
00382 return true;
00383 }
00384 else if( SOCKET_ERROR == nfds )
00385 {
00386 int save_errno = SocketError();
00387 switch( save_errno )
00388 {
00389 case EBADF:
00390
00391
00392
00393
00394
00395
00396 {
00397 SocketsLogLastError( LOG_ERROR, "select() EBADF.\n" );
00398 bool bFound = false;
00399 socket_foreach_deletable( suspect )
00400 {
00401 int tmp;
00402 int ret = ioctl( suspect->socket, I_GETSIG, &tmp );
00403 if( (-1 == ret) && (EBADF == SocketError()) )
00404 {
00405 Socket_LogError( suspect, LOG_ERROR, "select() BAD HANDLE: %d.\n", suspect->socket );
00406 Socket_Close( suspect );
00407 bFound = true;
00408 }
00409 }
00410
00411
00412 return bFound;
00413 }
00414 break;
00415 case EAGAIN:
00416 case EINTR:
00417
00418 break;
00419 case EINVAL:
00420
00421
00422 if( (1+nfds < 0) || (1+nfds > FD_SETSIZE) )
00423 {
00424 SocketsLogLastError( LOG_ERROR, "select() nfds out of range.\n" );
00425 return false;
00426 }
00427
00428
00429
00430
00431
00432
00433 default:
00434 SocketsLogLastError( LOG_ERROR, "select() failed.\n" );
00435
00436 SocketSetError(save_errno);
00437 return false;
00438 }
00439 }
00440 }
00441
00442 #endif
00443
00444
00445 {
00446 socket_foreach( sock )
00447 {
00448 assertobjptr(sock);
00449 if( stUninitialized != sock->type ppNotWindows(&& FD_ISSET(sock->socket,&fdwrites)) )
00450 {
00451 assertcodeptr(sock->vtab->WriteCycle);
00452 sock->vtab->WriteCycle(sock);
00453 }
00454 }
00455 }
00456
00457
00458 {
00459 socket_foreach( sock )
00460 {
00461 assertobjptr(sock);
00462 if( !Socket_ShouldIgnore(sock) ppNotWindows(&& FD_ISSET(sock->socket,&fdreads)) )
00463 {
00464 assertcodeptr(sock->vtab->ReadCycle);
00465 sock->vtab->ReadCycle(sock);
00466 }
00467 }
00468 }
00469
00470
00471 return true;
00472 }
00473
00478 const char* SocketsLastErrorString(void)
00479 {
00480 #ifdef WIN32
00481 static char szError[512];
00482 DWORD dw = SocketError();
00483 FormatMessage(
00484 FORMAT_MESSAGE_FROM_SYSTEM |
00485 FORMAT_MESSAGE_IGNORE_INSERTS |
00486 FORMAT_MESSAGE_MAX_WIDTH_MASK,
00487 NULL,
00488 dw,
00489 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00490 szError, sizeof(szError)/sizeof(*szError),
00491 NULL);
00492 return szError;
00493 #else
00494 return strerror(SocketError());
00495 #endif
00496 }
00497
00503 void SocketsLogLastError( unsigned mask, const char*fmt, ... )
00504 {
00505 va_list args;
00506 va_start( args, fmt );
00507 assertconst(fmt,1);
00508 debug_vlog(mask, fmt, args );
00509 LOG( mask, "%s\n", SocketsLastErrorString() );
00510 }
00511
00521 struct addrinfo *SocketsParseAddress( const char* szAddress )
00522 {
00523 char ipbuff[256];
00524 const char* port;
00525 const char* address;
00526 const char* scan;
00527 assertconst(szAddress,1);
00528 scan = address = szAddress;
00529
00530 while( ':' != *scan )
00531 {
00532 if( 0 == *scan )
00533 return NULL;
00534 scan++;
00535 }
00536
00537 if( *scan == '/' )
00538 {
00539 ++scan;
00540 if( *scan == '/' )
00541 {
00542 address = ++scan;
00543 while( ':' != *scan )
00544 {
00545 if( 0 == *scan )
00546 {
00547 LOG( LOG_ERROR, "SocketsParseAddress(%s) no ':port'.\n", szAddress );
00548 return NULL;
00549 }
00550 scan++;
00551 }
00552 }
00553 else
00554 {
00555 LOG( LOG_ERROR, "SocketsParseAddress(%s) found ':/' instead of '://'.\n", szAddress );
00556 return NULL;
00557 }
00558 }
00559 if( *scan == ':' )
00560 {
00561 size_t address_len;
00562 port = scan+1;
00563 address_len = (scan-address);
00564 if( address_len > sizeof(ipbuff) )
00565 {
00566 LOG( LOG_ERROR, "SocketsParseAddress(%s) address too long.\n", szAddress );
00567 return NULL;
00568 }
00569 memcpy(ipbuff,address,address_len);
00570 ipbuff[address_len] = 0;
00571 SocketsLogHostent( LOG_INFO, ipbuff );
00572 {
00573 struct addrinfo aiHints;
00574 struct addrinfo *aiList = NULL;
00575 memset(&aiHints, 0, sizeof(aiHints));
00576 aiHints.ai_family = AF_INET;
00577 aiHints.ai_socktype = SOCK_STREAM;
00578 aiHints.ai_flags = AI_CANONNAME;
00579 aiHints.ai_protocol = IPPROTO_TCP;
00580 if( 0 != getaddrinfo(ipbuff, port, &aiHints, &aiList) )
00581 {
00582 SocketsLogLastError( LOG_ERROR, "SocketsParseAddress(%s) failed.\n", szAddress );
00583 return NULL;
00584 }
00585 #if 1
00586 {
00587 struct addrinfo *ai = aiList;
00588 while( NULL != ai )
00589 {
00590 trace(( "%s: ", ai->ai_canonname ));
00591 traceip("Address:",ai->ai_addr);
00592 ai = ai->ai_next;
00593 }
00594 }
00595 #endif
00596 return aiList;
00597 }
00598 }
00599 return NULL;
00600 }
00601
00605 void SocketsLogHostent( uint32 logmask, const char* name )
00606 {
00607
00608 struct hostent* hostEntry;
00609 assertconst(name,1);
00610 hostEntry = gethostbyname(name);
00611 if( NULL == hostEntry )
00612 {
00613 struct in_addr ina;
00614 #ifdef WIN32
00615 uint32 inu = inet_addr(name);
00616 ina = *((struct in_addr*)&inu);
00617 #else
00618 if( 0 == inet_aton( name, &ina) )
00619 {
00620 SocketsLogLastError( LOG_ERROR, "inet_aton failed.\n" );
00621 return;
00622 }
00623 #endif
00624 hostEntry = gethostbyaddr( ppWindows((const char*))&ina, sizeof(ina), AF_INET );
00625 if( NULL == hostEntry )
00626 {
00627 SocketsLogLastError( LOG_ERROR, "gethostbyaddr failed.\n" );
00628 return;
00629 }
00630 }
00631 LOG( logmask, "Official name: %s\n", hostEntry->h_name);
00632 LOG( logmask, "Alternate names:\n");
00633 {
00634 const char** p = (const char** )hostEntry->h_aliases;
00635 while( *p )
00636 {
00637 LOG( logmask, "\t%s\n", *p++ );
00638 }
00639 }
00640 LOG( logmask, "Address type: ");
00641 switch (hostEntry->h_addrtype)
00642 {
00643 case AF_INET:
00644 LOG( logmask, "AF_INET\n");
00645 break;
00646 case AF_INET6:
00647 LOG( logmask, "AF_INET6\n");
00648 break;
00649 default:
00650 LOG( logmask, " %d\n", hostEntry->h_addrtype);
00651 break;
00652 }
00653
00654 if( hostEntry->h_length >= 4 )
00655 {
00656 struct in_addr **p = (struct in_addr **)hostEntry->h_addr_list;
00657 LOG( logmask, "Addresses Available:\n" );
00658 while(*p)
00659 {
00660 LOG( logmask, "\t%s\n", inet_ntoa(**p) );
00661 ++p;
00662 }
00663 }
00664 }
00665
00666
00671 static void Socket_Options( Socket* sock )
00672 {
00673 assertobjptr(sock);
00674 #ifdef WIN32
00675 {
00676
00677 uint32 iMode = 1;
00678 if( SOCKET_ERROR == ioctlsocket(sock->socket, FIONBIO, &iMode) )
00679 {
00680 SocketsLogLastError( LOG_ERROR, "%s ioctlsocket(%d)n", sock->label, sock->socket );
00681 }
00682 }
00683 #if 0
00684 {
00685
00686
00687 BOOL bOptVal = TRUE;
00688 DWORD dwError = 0L ;
00689 DWORD dwBytes = 0L ;
00690 struct tcp_keepalive sKA_Settings = {0}, sReturned = {0} ;
00691 setsockopt( sock->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&bOptVal, sizeof(BOOL) );
00692 sKA_Settings.onoff = 1 ;
00693 sKA_Settings.keepalivetime = 30000 ;
00694 sKA_Settings.keepaliveinterval = 5000 ;
00695 if (WSAIoctl( sock->socket, SIO_KEEPALIVE_VALS, &sKA_Settings,
00696 sizeof(sKA_Settings), &sReturned, sizeof(sReturned), &dwBytes,
00697 NULL, NULL) != 0)
00698 {
00699 SocketsLogLastError( LOG_ERROR, "Keepalive setup(%s)\n", sock->label );
00700 }
00701 }
00702 #endif
00703 #else
00704 {
00705
00706 int flags = fcntl( sock->socket, F_GETFL, 0 );
00707 if (-1 == flags )
00708 {
00709 SocketsLogLastError( LOG_ERROR, "%s fcntl(%d)n", sock->label, sock->socket );
00710 }
00711 else
00712 {
00713 flags |= O_NONBLOCK;
00714 fcntl( sock->socket, F_SETFL, flags );
00715 }
00716 }
00717 #endif
00718 }
00719
00720
00724 static void Generic_WriteCycle( Socket* sock )
00725 {
00726 int attempts;
00727 assertobjptr(sock);
00728 for( attempts = 0; attempts < 2; ++attempts )
00729 {
00730 size_t remain;
00731 if( (remain = RingBuff_Remain( &sock->output )) )
00732 {
00733 const uint8* buff;
00734 RingBuff_Peek( &sock->output, &buff, remain );
00735 int bytes = send( sock->socket, buff, remain, 0 );
00736 if( SOCKET_ERROR == bytes )
00737 {
00738 switch( SocketError() )
00739 {
00740 case 0:
00741
00742 case EWOULDBLOCK:
00743
00744 return;
00745 default:
00746
00747 SocketsLogLastError( LOG_ERROR, "Generic_WriteCycle(%s) receive failed\n", sock->label );
00748 Socket_Close( sock );
00749 return;
00750 }
00751 }
00752 else if( bytes > 0 )
00753 {
00754
00755 RingBuff_Pop( &sock->output, &buff, bytes );
00756 if( bytes < remain )
00757 {
00758
00759 return;
00760 }
00761 }
00762 if( stSendingFinal == sock->type && RingBuff_IsEmpty(&sock->output) )
00763 {
00764
00765 Socket_Close( sock );
00766 return;
00767 }
00768 }
00769 else
00770 {
00771
00772 return;
00773 }
00774 }
00775 }
00776
00782 static void Generic_ReadCycle( Socket* sock )
00783 {
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796 size_t available;
00797 assertobjptr(sock);
00798 available = RingBuff_Free(&sock->input);
00799 if( 0 < available )
00800 {
00801 uint8* space;
00802 RingBuff_Space( &sock->input, &space, available );
00803 int bytes = recv( sock->socket, space, available, 0 );
00804 Socket_Validate(sock);
00805 if( 0 == bytes )
00806 {
00807 Socket_Close( sock );
00808 return;
00809 }
00810 if( SOCKET_ERROR == bytes )
00811 {
00812 if( EWOULDBLOCK != SocketError() )
00813 {
00814 SocketsLogLastError( LOG_ERROR, "Generic_ReadCycle(%s) receive failed\n", sock->label );
00815 Socket_Close( sock );
00816 }
00817 return;
00818 }
00819
00820 RingBuff_Add( &sock->input, &space, (size_t)bytes );
00821 }
00822 ctl_serial serial;
00823 if( RingBuff_PopSerial( &sock->input, &serial ) )
00824 {
00825 sock->lastmsg = ctl_mstime();
00826 sock->appReceived( sock, &serial );
00827 }
00828 }
00829
00830
00831
00832
00833 static void Client_Close( Socket* sock )
00834 {
00835 }
00836 SockVTAB ClientVTAB =
00837 {
00838 Generic_ReadCycle,
00839 Generic_WriteCycle,
00840 Client_Close
00841 };
00842
00843
00849 Socket* Socket_Create_Client( const char* address )
00850 {
00851 Socket* sock;
00852 assertconst(address,1);
00853 sock = Socket_Create();
00854 if( NULL == sock )
00855 return NULL;
00856 sock->type = stClient;
00857 sock->timeout = int64_max;
00858 LOG( LOG_INFO, "Socket_Create_Client(%s)\n", address );
00859 sock->vtab = &ClientVTAB;
00860 strncpy(sock->label, "Client", countof(sock->label) );
00861 return sock;
00862 }
00863 Socket* Socket_Client_Connect( Socket* sock, const char* address )
00864 {
00865
00866 struct addrinfo * service = SocketsParseAddress( address );
00867 if( NULL == service )
00868 {
00869 Socket_Close( sock );
00870 return NULL;
00871 }
00872 sock->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
00873 if( sock->socket == INVALID_SOCKET )
00874 {
00875 SocketsLogLastError( LOG_ERROR, "Socket_Create_Client(%s) socket failed\n", address );
00876 Socket_Close( sock );
00877 return NULL;
00878 }
00879
00880 Socket_Options( sock );
00881 memcpy( &sock->socka_buff, service->ai_addr, min(service->ai_addrlen,sizeof(sock->socka_buff)) );
00882 LOG( LOG_INFO, "Client: %s\n", service->ai_canonname );
00883 freeaddrinfo(service);
00884 SocketLogIP(sock,LOG_INFO,"Address: ");
00885 if( SOCKET_ERROR == connect( sock->socket, (struct sockaddr*)&sock->address, sizeof(sock->address)) )
00886 {
00887 SocketsLogLastError( LOG_ERROR, "Socket_Create_Client(%s) connect failed.\n", address );
00888 Socket_Close( sock );
00889 return NULL;
00890 }
00891 return sock;
00892 }
00893
00894
00895
00896 static void Listener_ReadCycle(struct Socket* sock)
00897 {
00898
00899 SOCKET client;
00900 assertobjptr(sock);
00901 client = accept( sock->socket, NULL, NULL );
00902 if( INVALID_SOCKET == client )
00903 {
00904 if( EWOULDBLOCK != SocketError() )
00905 {
00906 SocketsLogLastError( LOG_ERROR, "Listener_ReadCycle(%s) accept failed\n", sock->label );
00907 }
00908 }
00909 else
00910 {
00911 sock->lastmsg = ctl_mstime();
00912 Socket_Create_Login( client );
00913 }
00914 }
00915
00916
00917
00918 static void Listener_Close( Socket* sock )
00919 {
00920 LOG( LOG_INFO, "%s Closed\n", sock->label );
00921 }
00922
00923
00924
00925 static void Listener_WriteCycle( Socket* sock )
00926 {
00927 RingBuff_Reset(&sock->output);
00928 }
00929 SockVTAB ListenerVTAB =
00930 {
00931 Listener_ReadCycle,
00932 Listener_WriteCycle,
00933 Listener_Close
00934 };
00935
00944 Socket* Socket_Create_Listener( const char* label, const char* address )
00945 {
00946 Socket* sock;
00947 struct addrinfo * service;
00948 assertconst(label,1);
00949 assertconst(address,1);
00950 LOG(LOG_STARTUP,"Socket_Create_Listener(%s,%s)\n", label, address );
00951 service = SocketsParseAddress( address );
00952 if( NULL == service )
00953 return NULL;
00954 sock = Socket_Create();
00955 if( NULL == sock )
00956 return NULL;
00957 sock->vtab = &ListenerVTAB;
00958 sock->type = stListener;
00959 sock->timeout = int64_max;
00960 strncpy( sock->label, label, countof(sock->label) );
00961 sock->socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP);
00962 if( sock->socket == INVALID_SOCKET )
00963 {
00964 SocketsLogLastError( LOG_ERROR, "Socket_Create_Listener(%s,%s) socket failed\n", sock->label,address );
00965 Socket_Close( sock );
00966 return NULL;
00967 }
00968
00969 Socket_Options( sock );
00970 {
00971
00972 memcpy( &sock->socka_buff, service->ai_addr, min(service->ai_addrlen,sizeof(sock->socka_buff)) );
00973 LOG( LOG_STARTUP, "Listen: %s\n", service->ai_canonname );
00974 freeaddrinfo(service);
00975 SocketLogIP(sock,LOG_INFO,"Address: ");
00976 if( SOCKET_ERROR == bind( sock->socket, (struct sockaddr*)&sock->ip, sizeof(sock->ip)) )
00977 {
00978 SocketsLogLastError( LOG_ERROR, "Socket_Create_Listener(%s,%s) bind failed.\n", sock->label,address );
00979 Socket_Close( sock );
00980 return NULL;
00981 }
00982 }
00983
00984 if( SOCKET_ERROR == listen( sock->socket, MAX_SOCKETS/2 ) )
00985 {
00986 SocketsLogLastError( LOG_ERROR, "Socket_Create_Listener(%s,%s) listen failed.\n", sock->label,address );
00987 Socket_Close( sock );
00988 return NULL;
00989 }
00990 return sock;
00991 }
00992
00993
00994
00995
00996
00997
00998
00999
01000 const char* defcbHTTP(void)
01001 {
01002 return
01003 "<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\">"
01004 "<body bgcolor=\"#000000\" text=\"#ff0000\" link=\"#ff0000\" vlink=\"#800000\">"
01005 "<font size=\"7\"><center><br/><br/><br/><br/><b>"
01006 "<a href=\"http://en.wikipedia.org/wiki/Liar_paradox\">NOT A WEB SERVER</a>"
01007 "</b></center></font></body></html>"
01008 "\n";
01009 }
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019 const char* defcbFlashPolicy(void)
01020 {
01021 return
01022 "<?xml version=\"1.0\"?>\n"
01023 "<!DOCTYPE cross-domain-policy SYSTEM \"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd\">\n"
01024 "<cross-domain-policy>\n"
01025 " <allow-access-from domain=\"*\" to-ports=\"*\" />\n"
01026 "</cross-domain-policy>\n";
01027 }
01028
01029 static MLCallback cbHTTP = defcbHTTP;
01030 static MLCallback cbFlashPolicy = defcbFlashPolicy;
01035 MLCallback SocketsSetHTTP( MLCallback callback )
01036 {
01037 MLCallback prev = cbHTTP;
01038 cbHTTP = NULL == callback ? defcbHTTP: callback;
01039 assertcodeptr(cbHTTP);
01040 return prev;
01041 }
01046 MLCallback SocketsSetFlashPolicy( MLCallback callback )
01047 {
01048 MLCallback prev = cbFlashPolicy;
01049 cbFlashPolicy = NULL == callback ? defcbFlashPolicy: callback;
01050 assertcodeptr(cbFlashPolicy);
01051 return prev;
01052 }
01053
01054
01055
01056
01057
01058 static void Login_ReadCycle(struct Socket* sock)
01059 {
01060
01061 size_t available;
01062 assertobjptr(sock);
01063 available = RingBuff_Free(&sock->input);
01064 if( 0 < available )
01065 {
01066 uint8* space;
01067 RingBuff_Space(&sock->input,&space,available);
01068 int bytes = recv( sock->socket, space, available, 0 );
01069 Socket_Validate(sock);
01070 if( 0 == bytes )
01071 {
01072 Socket_Close( sock );
01073 return;
01074 }
01075 if( SOCKET_ERROR == bytes )
01076 {
01077 if( EWOULDBLOCK != SocketError() )
01078 {
01079 SocketsLogLastError( LOG_ERROR, "Login_ReadCycle(%s) receive failed\n", sock->label );
01080 Socket_Close( sock );
01081 }
01082 return;
01083 }
01084
01085 RingBuff_Add( &sock->input, &space, (size_t)bytes );
01086 }
01087 available = RingBuff_Remain(&sock->input);
01088 {
01089
01090 const char szGET[] = "GET / HTTP";
01091 const char szQuery[] = "<policy-file-request/>";
01092 if( sizeof(szQuery) == available )
01093 {
01094 const uint8* peek;
01095 if( RingBuff_Peek( &sock->input, &peek, sizeof(szQuery) )
01096 && 0 == memcmp( peek, szQuery, sizeof(szQuery) ) )
01097 {
01098
01099
01100 const char* xmlSpew = cbFlashPolicy();
01101 RingBuff_Reset( &sock->input );
01102 Socket_Write( sock, xmlSpew, 1+strlen(xmlSpew) );
01103
01104 sock->type = stSendingFinal;
01105 sock->timeout = 10000;
01106 Socket_Validate(sock);
01107 strncpy(sock->label,szconst(char,szQuery),countof(sock->label));
01108 return;
01109 }
01110 }
01111 if( sizeof(szGET) < available )
01112 {
01113 const uint8* peek;
01114 if( RingBuff_Peek( &sock->input, &peek, sizeof(szQuery) )
01115 && 0 == memcmp( peek, szGET, sizeof(szGET)-1 ) )
01116 {
01117
01118
01119
01120
01121 const char htmlSpewHead[] =
01122 "HTTP/1.1 200 OK\n"
01123 "Content-Type: text/html\n"
01124 "\n";
01125 const char* htmlSpewBody = cbHTTP();
01126 RingBuff_Reset( &sock->input );
01127 Socket_Write( sock, htmlSpewHead, sizeof(htmlSpewHead)-1 );
01128 Socket_Write( sock, htmlSpewBody, strlen(htmlSpewBody) );
01129
01130 sock->type = stSendingFinal;
01131 sock->timeout = 10000;
01132 Socket_Validate(sock);
01133 strncpy(sock->label,szconst(char,szGET),countof(sock->label));
01134 SocketLogIP( sock, LOG_SECURITY, "Bogus HTTP connection: " );
01135 return;
01136 }
01137 }
01138 if( available >= 2 )
01139 {
01140 ctl_serial serial;
01141 if( RingBuff_PopSerial( &sock->input, &serial ) )
01142 {
01143 sock->lastmsg = ctl_mstime();
01144 sock->appReceived( sock, &serial );
01145 }
01146 }
01147 }
01148 }
01149
01150
01151
01152
01153 static void Login_Close( Socket* sock )
01154 {
01155 }
01156 SockVTAB LoginVTAB =
01157 {
01158 Login_ReadCycle,
01159 Generic_WriteCycle,
01160 Login_Close
01161 };
01162
01168 Socket* Socket_Create_Login( SOCKET isock )
01169 {
01170 Socket* sock = Socket_Create();
01171 if( NULL == sock )
01172 return NULL;
01173 sock->vtab = &LoginVTAB;
01174 sock->type = stLogin;
01175 sock->socket = isock;
01176 sock->timeout = 5000;
01177 {
01178
01179 size_t addrlen = sizeof(sock->socka_buff);
01180 getpeername( sock->socket, &sock->address, &addrlen );
01181 }
01182 cstrncpy(char)( sock->label, "Login", countof(sock->label) );
01183
01184
01185 Socket_Options( sock );
01186
01187 assertcodeptr(login_callback);
01188 login_callback(sock);
01189 return sock;
01190 }
01191
01192
01193
01194
01195 static void User_Close( Socket* sock )
01196 {
01197 }
01198 SockVTAB UserVTAB =
01199 {
01200 Generic_ReadCycle,
01201 Generic_WriteCycle,
01202 User_Close
01203 };
01214 Socket* Socket_Create_User( Socket* sock, const char* label )
01215 {
01216 assertobjptr(sock);
01217 assertconst(label,1);
01218 sock->vtab = &UserVTAB;
01219 sock->type = stUser;
01220 sock->timeout = (15*60*1000);
01221 cstrncpy(char)(sock->label, label, countof(sock->label));
01222
01223
01224 assertcodeptr(user_callback);
01225 user_callback(sock);
01226 return sock;
01227 }
01228
01229
01230
01231
01232 static void Raw_ReadCycle( Socket* sock )
01233 {
01234
01235 size_t available;
01236 assertobjptr(sock);
01237 available = RingBuff_Free(&sock->input);
01238 if( 0 < available )
01239 {
01240 uint8* space;
01241 RingBuff_Space(&sock->input, &space, available );
01242 int bytes = recv( sock->socket, space, available, 0 );
01243 if( 0 == bytes )
01244 {
01245 Socket_Close( sock );
01246 return;
01247 }
01248 if( SOCKET_ERROR == bytes )
01249 {
01250 if( EWOULDBLOCK != SocketError() )
01251 {
01252 SocketsLogLastError( LOG_ERROR, "Raw_ReadCycle(%s) receive failed\n", sock->label );
01253 Socket_Close( sock );
01254 }
01255 return;
01256 }
01257
01258 RingBuff_Add( &sock->input, &space, (size_t)bytes );
01259 }
01260 {
01261 size_t remain = RingBuff_Remain(&sock->input);
01262 const uint8* peek;
01263 if( RingBuff_Peek( &sock->input, &peek, remain ) )
01264 {
01265 ctl_serial packet;
01266 sock->lastmsg = ctl_mstime();
01267 ctl_serial_init( &packet, (uint8*)peek, peek+remain );
01268
01269
01270
01271
01272
01273
01274 sock->appReceived( sock, &packet );
01275 }
01276 }
01277 }
01284 const uint8* Socket_Raw_Consume( Socket* sock, size_t size )
01285 {
01286 const uint8* data;
01287 assertobjptr(sock);
01288 RingBuff_Pop( &sock->input, &data, size );
01289 return data;
01290 }
01291
01292
01293
01294
01295 static void Raw_Close( Socket* sock )
01296 {
01297 }
01298 SockVTAB RawVTAB =
01299 {
01300 Raw_ReadCycle,
01301 Generic_WriteCycle,
01302 Raw_Close
01303 };
01312 Socket* Socket_Create_Raw( Socket* sock )
01313 {
01314 assertobjptr(sock);
01315 sock->vtab = &RawVTAB;
01316 sock->type = stRaw;
01317 sock->timeout = 15000;
01318 cstrncpy(char)( sock->label, "Raw", countof(sock->label) );
01319
01320
01321 assertcodeptr(user_callback);
01322 user_callback(sock);
01323 return sock;
01324 }
01325
01330 Socket* Socket_Create(void)
01331 {
01332 Socket* sock;
01333 size_t index;
01334
01335 ctl_fp_calloc(SocketPool, sockPool, sock );
01336 if( NULL == sock )
01337 return NULL;
01338 sock->type = stUninitialized;
01339 sock->timeout = 5000;
01340 ++cSockActive;
01341 --cSockFree;
01342 sock->created = sock->lastmsg = ctl_mstime();
01343
01344 {
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357 static uint32 seq = 0;
01358 index = ctl_fp_index(SocketPool, sockPool, sock );
01359 sock->id = index | (seq++&0xffff)<<16;
01360 }
01361
01362
01363
01364 dll_push_back(Socket,active, socksActive, sock );
01365
01366
01367 sock->socket = INVALID_SOCKET;
01368
01369
01370 strncpy(sock->label, "Socket", countof(sock->label) );
01371
01372
01373
01374
01375
01376 Socket_Customize( sock, 0,0,0 );
01377
01378
01379 sock->appReceived = Socket_DefaultReceived;
01380 sock->appDisconnect = Socket_DefaultCallback;
01381 return sock;
01382 }
01383
01384
01385 static void Socket_Free( Socket* sock )
01386 {
01387 size_t index;
01388 Socket_Validate(sock);
01389 index = ctl_fp_index(SocketPool, sockPool, sock );
01390 assert( index >= 0 && index < MAX_SOCKETS );
01391 sock->type = stUninitialized;
01392 sock->id = 0;
01393
01394
01395 if( NULL != sock->pInput && SOCK_INPUT_DEFAULTPTR(index) != sock->pInput )
01396 ctl_free( sock->pInput );
01397 if( NULL != sock->pOutput && SOCK_OUTPUT_DEFAULTPTR(index) != sock->pOutput )
01398 ctl_free( sock->pOutput );
01399 if( NULL != sock->pAppHeap && SOCK_HEAP_DEFAULTPTR(index) != sock->pAppHeap )
01400 ctl_free( sock->pAppHeap );
01401
01402 dll_erase(Socket,active, socksActive, sock );
01403 ctl_fp_free(SocketPool, sockPool, sock );
01404 --cSockActive;
01405 ++cSockFree;
01406 }
01407
01421 Socket* Socket_Customize( Socket* sock, size_t input, size_t output, size_t heap )
01422 {
01423 size_t index;
01424 assertobjptr(sock);
01425 index = ctl_fp_index(SocketPool, sockPool, sock );
01426 assert( index >= 0 && index < MAX_SOCKETS );
01427
01428 if( NULL != sock->pInput && SOCK_INPUT_DEFAULTPTR(index) != sock->pInput )
01429 ctl_free( sock->pInput );
01430 if( NULL != sock->pOutput && SOCK_OUTPUT_DEFAULTPTR(index) != sock->pOutput )
01431 ctl_free( sock->pOutput );
01432 if( NULL != sock->pAppHeap && SOCK_HEAP_DEFAULTPTR(index) != sock->pAppHeap )
01433 ctl_free( sock->pAppHeap );
01434 if( input > sockInSize )
01435 {
01436 ctl_malloc( sock->pInput, input + sizeof(uint32));
01437 }
01438 else
01439 {
01440 input = sockInSize;
01441 sock->pInput = SOCK_INPUT_DEFAULTPTR(index);
01442 }
01443 if( output > sockOutSize )
01444 {
01445 ctl_malloc( sock->pOutput, output + sizeof(uint32) );
01446 }
01447 else
01448 {
01449 output = sockOutSize;
01450 sock->pOutput= SOCK_OUTPUT_DEFAULTPTR(index);
01451 }
01452 if( heap > sockHeapSize )
01453 {
01454 ctl_malloc( sock->pAppHeap, heap + sizeof(uint32) );
01455 }
01456 else
01457 {
01458 heap = sockHeapSize;
01459 sock->pAppHeap = SOCK_HEAP_DEFAULTPTR(index);
01460 }
01461
01462 memset( sock->pInput, 0, input );
01463 RingBuff_Init( &sock->input, sock->pInput, sockInSize );
01464 memset( sock->pInput, 0, output );
01465 RingBuff_Init( &sock->output, sock->pOutput, sockOutSize );
01466
01467 memset( sock->pAppHeap, 0, heap );
01468 ctl_heap_init( &sock->appheap, sock->pAppHeap, sockHeapSize );
01469
01470 *((uint32*)(sock->pInput + input)) = GUARD_BYTES;
01471 *((uint32*)(sock->pOutput + output)) = GUARD_BYTES;
01472 *((uint32*)(sock->pAppHeap + heap)) = GUARD_BYTES;
01473 return sock;
01474 }
01475
01476
01483 void Socket_LogError( Socket* sock, unsigned mask, const char*fmt, ... )
01484 {
01485 va_list args;
01486 va_start( args, fmt );
01487 int save_errno = SocketError();
01488 assertconst(fmt,1);
01489 debug_vlog(mask, fmt, args );
01490 SocketLogIP(sock,mask,"");
01491 SocketSetError(save_errno);
01492 LOG( mask, "%s\n", SocketsLastErrorString() );
01493 }
01494
01495 #ifdef DEBUG
01496
01500 void Socket_Validate( Socket* sock )
01501 {
01502 size_t index;
01503 assertobjptr(sock);
01504 index = ctl_fp_index(SocketPool, sockPool, sock );
01505 assert( NULL != sock->pInput );
01506 assert( NULL != sock->pOutput );
01507 assert( NULL != sock->pAppHeap );
01508 if( SOCK_INPUT_DEFAULTPTR(index) == sock->pInput )
01509 {
01510 assert( *((uint32*)(sock->pInput + sockInSize)) == GUARD_BYTES );
01511 }
01512 else
01513 {
01514 assert( *((uint32*)(sock->pInput + ctl_size(sock->pInput) - sizeof(uint32))) == GUARD_BYTES );
01515 }
01516 if( SOCK_OUTPUT_DEFAULTPTR(index) == sock->pOutput )
01517 {
01518 assert( *((uint32*)(sock->pOutput + sockOutSize)) == GUARD_BYTES );
01519 }
01520 else
01521 {
01522 assert( *((uint32*)(sock->pOutput + ctl_size(sock->pOutput) - sizeof(uint32))) == GUARD_BYTES );
01523 }
01524 if( SOCK_HEAP_DEFAULTPTR(index) == sock->pAppHeap )
01525 {
01526 assert( *((uint32*)(sock->pAppHeap + sockHeapSize)) == GUARD_BYTES );
01527 }
01528 else
01529 {
01530 assert( *((uint32*)(sock->pAppHeap + ctl_size(sock->pAppHeap) - sizeof(uint32))) == GUARD_BYTES );
01531 }
01532 }
01533 #endif
01534
01539 void Socket_Close( Socket* sock )
01540 {
01541 assertobjptr(sock);
01542 trace(( "Socket_Close(%s)\n", sock->label ));
01543
01544 Socket_Validate(sock);
01545 sock->type = stUninitialized;
01546 sock->id = 0;
01547
01548
01549 if( INVALID_SOCKET != sock->socket )
01550 {
01551 if( SOCKET_ERROR == closesocket(sock->socket) )
01552 SocketsLogLastError( LOG_ERROR, "Socket_Close(%d,%s) closesocket failed.\n", sock->socket, sock->label );
01553 sock->socket = INVALID_SOCKET;
01554 }
01555
01556
01557 assertcodeptr(sock->appDisconnect);
01558 sock->appDisconnect(sock);
01559
01560
01561 assertcodeptr(sock->vtab->Close);
01562 sock->vtab->Close(sock);
01563
01564
01565
01566 sock->appReceived = Socket_DefaultReceived;
01567 sock->appDisconnect = Socket_DefaultCallback;
01568 }
01569
01577 bool Socket_Write( Socket* sock, const void* buff, size_t count )
01578 {
01579 assertobjptr(sock);
01580 assertconst(buff,count);
01581 if( Socket_ShouldIgnore(sock) )
01582 {
01583 return false;
01584 }
01585 else
01586 {
01587 bool bRet = RingBuff_CopyTo( &sock->output, buff, count );
01588 if( !bRet )
01589 {
01590 SocketsLogLastError( LOG_ERROR, "Socket_Write(%s,%u) failed\n", sock->label, count );
01591 Socket_Close( sock );
01592 return false;
01593 }
01594 return true;
01595 }
01596 }
01597
01605 bool Socket_Alloc_Serial( Socket* sock, ctl_serial* serial, size_t size )
01606 {
01607 assertobjptr(sock);
01608 assertobjptr(serial);
01609 if( Socket_ShouldIgnore(sock) )
01610 {
01611 return false;
01612 }
01613 else
01614 {
01615 bool bRet = RingBuff_AddSerial( &sock->output, serial, size + 2 );
01616 if( bRet )
01617 {
01618 return true;
01619 }
01620 else
01621 {
01622 SocketsLogLastError( LOG_ERROR, "Socket_Alloc_Serial(%s,%u) failed\n", sock->label, size );
01623 Socket_Close( sock );
01624 return false;
01625 }
01626 }
01627 }
01628
01635 bool Socket_Write_Serial( Socket* sock, const ctl_serial* serial )
01636 {
01637 assertobjptr(sock);
01638 assertobjconst(serial);
01639 if( Socket_ShouldIgnore(sock) )
01640 {
01641 return false;
01642 }
01643 else
01644 {
01645 size_t length = ctl_serial_total( serial );
01646 bool bRet = RingBuff_CopyTo( &sock->output, serial->begin, length );
01647 if( !bRet )
01648 {
01649 SocketsLogLastError( LOG_ERROR, "Socket_Write_Serial(%s,%u) failed\n", sock->label, length );
01650 Socket_Close( sock );
01651 return false;
01652 }
01653 return true;
01654 }
01655 }