static ftRequest_t* FT_CreateRequest(const char* address, const char* url) { void* buf; ftRequest_t* request; request = Z_Malloc(sizeof(ftRequest_t)); if(request == NULL) return NULL; Com_Memset(request, 0, sizeof(ftRequest_t)); request->lock = qtrue; request->finallen = -1; request->socket = -1; request->transfersocket = -1; if(address != NULL) { Q_strncpyz(request->address, address, sizeof(request->address)); /* Open the connection */ request->socket = NET_TcpClientConnect(request->address); if(request->socket < 0) { request->socket = -1; FT_FreeRequest(request); return NULL; } } buf = Z_Malloc(INITIAL_BUFFERLEN); if( buf == NULL) { FT_FreeRequest(request); return NULL; } MSG_Init(&request->recvmsg, buf, INITIAL_BUFFERLEN); buf = Z_Malloc(INITIAL_BUFFERLEN); if( buf == NULL) { FT_FreeRequest(request); return NULL; } MSG_Init(&request->sendmsg, buf, INITIAL_BUFFERLEN); if(url != NULL) { Q_strncpyz(request->url, url, sizeof(request->url)); } request->startTime = Sys_Milliseconds(); return request; }
qboolean PHandler_TcpConnect(int pID, const char* remote, int connection) { if(pluginFunctions.plugins[pID].sockets[connection].sock < 1){ pluginFunctions.plugins[pID].sockets[connection].sock = NET_TcpClientConnect( remote ); if(pluginFunctions.plugins[pID].sockets[connection].sock < 1){ Com_Printf("Plugins: Notice! Error connecting to server: %s for plugin #%d!\n", remote, pID); return qfalse; } NET_StringToAdr(remote, &pluginFunctions.plugins[pID].sockets[connection].remote, NA_UNSPEC); return qtrue; } Com_PrintError("Plugin_TcpConnect: Connection id %d is already in use for plugin #%d!\n",connection ,pID ); return qfalse; }
static int FTP_SendReceiveData(ftRequest_t* request) { char* line; char command[MAX_STRING_CHARS]; int status, bytes; byte* buf; netadr_t pasvadr; char stringlinebuf[MAX_STRING_CHARS]; status = FT_ReceiveData(request); if (status == -1 && request->stage < 9999) { return -1; } if(status == 0 && request->stage < 9999) { status = FT_SendData(request); } if (status == -1 && request->stage < 9999) { return -1; } while ((line = MSG_ReadStringLine(&request->recvmsg, stringlinebuf, sizeof(stringlinebuf))) && line[0] != '\0' ) { if(isNumeric(line, 0) == qfalse) continue; request->code = atoi(line); if(request->stage > 60) Com_DPrintf("\n"); Com_DPrintf("Response Code = %d\n", request->code); if (request->stage < 0) { continue; } switch (request->code) { case 220: if(request->stage == 0) { // Initial OK response received / Com_DPrintf("FTP_SendReceiveData: Inital OK response received\n"); request->stage = 1; }else { Com_PrintWarning("\nFTP_SendReceiveData: Received: %s - Should not happen!\n", line); } break; case 202: if(request->stage < 21 && request->stage > 10) { request->stage = 21; }else { Com_Printf("\nFTP_SendReceiveData: Received unexpected response: %s - Will abort!\n", line); request->stage = -20; } break; case 331: if(request->stage == 10) { Com_DPrintf("FTP_SendReceiveData: Need Password\n"); request->stage = 11; }else if(request->stage == 16){ Com_DPrintf("FTP_SendReceiveData: Need Password\n"); request->stage = 17; }else { Com_Printf("FTP_SendReceiveData: Received unexpected response: %s - Will abort!\n", line); request->stage = -20; } break; case 332: if(request->stage == 10 || request->stage == 12) { Com_DPrintf("FTP_SendReceiveData: Need Account\n"); request->stage = 15; }else { Com_Printf("\nFTP_SendReceiveData: Received unexpected response: %s - Will abort!\n", line); request->stage = -20; } break; case 230: if (request->stage <= 20) { Com_DPrintf("FTP_SendReceiveData: Logged in OK\n"); request->stage = 21; }else { Com_Printf("\nFTP_SendReceiveData: Received unexpected response: %s - Will abort!\n", line); request->stage = -20; } break; case 227: if(request->stage == 36) { FTP_GetPassiveAddress(line, &pasvadr); if(pasvadr.type == NA_IP) { Com_DPrintf("FTP_SendReceiveData: Entering Passive Mode at %s OK\n", NET_AdrToString(&pasvadr)); request->transfersocket = NET_TcpClientConnect(NET_AdrToString(&pasvadr)); if(request->transfersocket < 0) { request->transfersocket = -1; return -1; } request->stage = 41; }else { Com_PrintWarning("FTP_SendReceiveData: Couldn't read the address/port of passive mode response\n"); return -1; } }else { Com_Printf("\nFTP_SendReceiveData: Received unexpected response: %s - Will abort!\n", line); request->stage = -20; } break; case 229: if(request->stage == 32) { FTP_GetExtendedPassiveAddress(line, request->address, &pasvadr); if(pasvadr.type == NA_IP || pasvadr.type == NA_IP6) { Com_DPrintf("FTP_SendReceiveData: Entering Extended Passive Mode at %s OK\n", NET_AdrToString(&pasvadr)); request->transfersocket = NET_TcpClientConnect(NET_AdrToString(&pasvadr)); if(request->transfersocket < 0) { request->transfersocket = -1; return -1; } request->stage = 41; }else { Com_PrintWarning("FTP_SendReceiveData: Couldn't read the address/port of passive mode response\n"); return -1; } }else { Com_Printf("\nFTP_SendReceiveData: Received unexpected response: %s - Will abort!\n", line); request->stage = -20; } break; case 213: if(request->stage == 50) { bytes = atoi(&line[4]); Com_DPrintf("FTP_SendReceiveData: Requested file will have %d bytes\n", bytes); if(bytes < 1 || bytes > 1024*1024*1024) { Com_PrintWarning("FTP_SendReceiveData: Requested file would exceed %d bytes. Will not download!\n", 1024*1024*1024); } buf = Z_Malloc(bytes); if( buf == NULL) { Com_PrintWarning("FTP_SendReceiveData: Failed to allocate %d bytes for download file!\n", bytes); return -1; } MSG_Init(&request->transfermsg, buf, bytes); request->stage = 51; } break; case 150: case 125: if (request->stage == 60) { request->stage = 61; Com_DPrintf("FTP_SendReceiveData: Begin File Transfer\n"); } break; case 226: /* File transfer is completed from the servers view */ if(request->stage < 9999) request->stage = 9999; break; case 221: if(request->stage < 10000) { Com_Printf("\nThe FTP server closed the control connection before the transfer was completed!\n"); request->stage = -1; } break; case 228: Com_Printf( "\nLong Passive Mode not supported and not requested!\n" ); request->stage = -20; break; case 120: Com_Printf( "The FTP server is not ready at the moment!\n" ); request->stage = -20; break; case 231: if(request->stage < 10000) { Com_Printf("\nThe FTP server logged us out before the transfer was completed!\n"); request->stage = -20; } break; case 350: if(request->stage < 10000) { Com_Printf("\nThe FTP server returned \'%s\' before the transfer was completed. Must not happen!\n", line); request->stage = -20; } break; case 421: request->stage = -1; break; case 500: case 501: case 502: case 503: if (request->stage == 32) { request->stage = 35; Com_DPrintf("FTP_SendReceiveData: Command EPSV is not implemented on FTP server. Trying PASV...\n"); break; }else if (request->stage == 36) { Com_Printf("FTP_SendReceiveData: FTP Server does not support passive mode. Request failed!\n"); request->stage = -10; } default: if (request->code >= 200 && request->code < 300 && request->stage >= 30){ Com_DPrintf("\n"); Com_DPrintf("FTP_SendReceiveData: %s\n", line); request->stage ++; break; }else if (request->code >= 400) { Com_Printf("\nThe FTP server connection got ended with the message: %s\n", line); request->stage = -20; } break; } } switch(request->stage) { case 1: /* Waiting for OK response code (220) */ Com_sprintf(command, sizeof(command), "USER %s\r\n", "anonymous"); FT_AddData(request, command, strlen(command)); request->stage = 10; break; case 11: Com_sprintf(command, sizeof(command), "PASS %s\r\n", "*****@*****.**"); FT_AddData(request, command, strlen(command)); request->stage = 12; break; case 15: Com_sprintf(command, sizeof(command), "ACCT %s\r\n", "nil"); FT_AddData(request, command, strlen(command)); request->stage = 16; break; case 17: Com_sprintf(command, sizeof(command), "PASS %s\r\n", "*****@*****.**"); FT_AddData(request, command, strlen(command)); request->stage = 20; break; case 21: Com_sprintf(command, sizeof(command), "TYPE I\r\n"); FT_AddData(request, command, strlen(command)); request->stage = 30; break; case 31: Com_sprintf(command, sizeof(command), "EPSV\r\n"); FT_AddData(request, command, strlen(command)); request->stage = 32; break; case 35: Com_sprintf(command, sizeof(command), "PASV\r\n"); FT_AddData(request, command, strlen(command)); request->stage = 36; break; case 41: Com_sprintf(command, sizeof(command), "SIZE %s\r\n", request->url); FT_AddData(request, command, strlen(command)); request->stage = 50; break; case 51: Com_sprintf(command, sizeof(command), "RETR %s\r\n", request->url); FT_AddData(request, command, strlen(command)); request->stage = 60; break; case 61: /* Receive new bytes */ request->transferactive = qtrue; status = NET_ReceiveData(request->transfersocket, &request->transfermsg); if (status == -1){ request->transfersocket = -1; }else if(status == -2){ request->transfersocket = -1; } if(request->transfermsg.cursize == request->transfermsg.maxsize && request->transfermsg.maxsize != 0) { /* Comple file retrived */ request->stage = 9999; break; }else if(request->transfersocket == -1){ request->stage = -20; } break; case 9999: status = -1; request->transferactive = qfalse; if(request->transfersocket >= 0) status = NET_ReceiveData(request->transfersocket, &request->transfermsg); if (status == -1 || status == -2){ request->transfersocket = -1; } if(request->transfermsg.cursize == request->transfermsg.maxsize && request->transfermsg.maxsize != 0) { /* Comple file retrived */ Com_sprintf(command, sizeof(command), "QUIT\r\n"); FT_AddData(request, command, strlen(command)); request->stage = 10000; break; }else { Com_Printf("\nThe FTP server closed the data connection before the transfer was completed!\n"); request->stage = -20; break; } case -20: request->transferactive = qfalse; Com_Printf("\nFTP File Transfer has failed!\n"); case -10: request->transferactive = qfalse; if(request->socket >= 0 ) { Com_sprintf(command, sizeof(command), "QUIT\r\n", request->url); FT_AddData(request, command, strlen(command)); } request->stage = -1; break; case -1: Com_Printf("\n"); return -1; break; case 10000: request->transferactive = qfalse; if(request->socket >= 0) { NET_TcpCloseSocket(request->socket); request->socket = -1; } if(request->transfersocket >= 0) { NET_TcpCloseSocket(request->transfersocket); request->transfersocket = -1; } if(request->recvmsg.data != NULL) { Z_Free(request->recvmsg.data); request->recvmsg.data = NULL; } if(request->transfermsg.data == NULL) { request->stage = -1; Com_PrintError("\nReceived complete message but message buffer is NULL!\n"); break; } Com_Memcpy(&request->recvmsg, &request->transfermsg, sizeof(msg_t)); Com_Memset(&request->transfermsg, 0, sizeof(msg_t)); request->contentLength = request->recvmsg.cursize; request->headerLength = 0; request->stage = 10001; request->code = 200; Q_strncpyz(request->status, "OK", sizeof(request->status)); break; case 10001: Com_Printf("\n"); return 1; default: return 0; } return 0; }