//------------------------------------ static void _ftp_deinit(uint8_t unreg) { closeCmdSocket(unreg); free(ftpCmdSocket); ftpCmdSocket = NULL; closeDataSocket(); free(ftpDataSocket); ftpDataSocket = NULL; free( pDomain4Dns); pDomain4Dns=NULL; free( ftpuser); ftpuser=NULL; free( ftppass); ftppass=NULL; free( ftpfile); ftpfile=NULL; free( recvBuf); recvBuf=NULL; free( recvDataBuf); recvDataBuf=NULL; free(ftpresponse); ftpresponse = NULL; if ((gL != NULL) & (unreg == 0)) ftp_log("[FTP end] FTP SESSION CLOSED.\r\n"); status = FTP_NOT_CONNECTED; }
bool YapClient::sendSyncCommand() { char pktHeader[4] = { 0, 0, 0, 0 }; uint16_t pktLen; char * ppp = 0; if (d->cmdPacket->length() == 0) { fprintf(stderr, "Command is empty\n"); return false; } pktLen = 0; ::memset(pktHeader, 0, sizeof(pktHeader)); pktLen = d->cmdPacket->length(); pktLen = bswap_16(pktLen); ::memcpy(pktHeader, &pktLen, 2); pktHeader[3] = kPacketFlagSyncMask; if (!writeSocket(d->cmdSocketFd, pktHeader, 4)) goto Detached; if (!writeSocket(d->cmdSocketFd, (char*) d->cmdBuffer, d->cmdPacket->length())) goto Detached; pktLen = 0; ::memset(pktHeader, 0, sizeof(pktHeader)); if (!readSocketSync(d->cmdSocketFd, pktHeader, 4)) goto Detached; ppp = ((char *)&pktHeader[0]); pktLen = *((uint16_t*) ppp); pktLen = bswap_16(pktLen); if (pktLen > kMaxMsgLen) { fprintf(stderr, "YAP: Message too large %u > %u\n", pktLen, kMaxMsgLen); goto Detached; } if (!readSocketSync(d->cmdSocketFd, (char*) d->replyBuffer, pktLen)) goto Detached; d->replyPacket->reset(); d->replyPacket->setReadTotalLength(pktLen); return true; Detached: serverDisconnected(); closeMsgSocket(); closeCmdSocket(); return false; }
YapClient::~YapClient() { if(d->msgServerIoSource != NULL) { g_source_destroy(d->msgServerIoSource); d->msgServerIoSource = NULL; } if(d->msgServerIoChannel != NULL) { g_io_channel_unref(d->msgServerIoChannel); d->msgServerIoChannel = NULL; } if(d->msgServerSocketFd != -1) { close(d->msgServerSocketFd); d->msgServerSocketFd = -1; } if (d->msgServerSocketPostfix) free(d->msgServerSocketPostfix); ::unlink(d->msgServerSocketPath); closeMsgSocket(); closeCmdSocket(); // We use mainLoop != NULL as a test to tell whether we allocated a loop & context during init(). // In the case where we're using the default main context, we never allocate a loop. if(d->mainLoop != NULL) { g_main_loop_unref(d->mainLoop); g_main_context_unref(d->mainCtxt); } delete d->msgPacket; delete d->cmdPacket; delete d->replyPacket; delete[] d->msgBuffer; delete[] d->cmdBuffer; delete[] d->replyBuffer; delete d; d = NULL; }
void YapClient::ioCallback(GIOChannel* channel, GIOCondition condition) { if (d == NULL) { fprintf(stderr, "YAP: ioCallback was executing on a null YapClientPrv!"); return; } if (channel == d->msgServerIoChannel) { // Server connected to our message socket. Created a new msg socket for it struct sockaddr_un socketAddr; socklen_t socketAddrLen; memset(&socketAddr, 0, sizeof(socketAddr)); memset(&socketAddrLen, 0, sizeof(socketAddrLen)); d->msgSocketFd = ::accept(d->msgServerSocketFd, (struct sockaddr*) &socketAddr, &socketAddrLen); // Create a new io channel for the receiving messages from the server d->msgIoChannel = g_io_channel_unix_new(d->msgSocketFd); d->msgIoSource = g_io_create_watch(d->msgIoChannel, (GIOCondition) (G_IO_IN | G_IO_HUP)); g_source_set_callback(d->msgIoSource, (GSourceFunc) YapClientPriv::ioCallback, this, NULL); g_source_attach(d->msgIoSource, d->mainCtxt); } else if (channel == d->cmdIoChannel) { if (condition & G_IO_HUP) { g_message("YAP: Server disconnected command socket"); closeMsgSocket(); closeCmdSocket(); serverDisconnected(); } } else if (channel == d->msgIoChannel) { char pktHeader[4] = { 0, 0, 0, 0 }; uint16_t pktLen = 0; char * ppp = 0; // We either got a message or a server disconnect if (condition & G_IO_HUP) goto Detached; // Get the packet header if (!readSocket(d->msgSocketFd, pktHeader, 4)) { fprintf(stderr, "YAP: Failed to read packet header\n"); goto Detached; } ppp = ((char *)&pktHeader[0]); pktLen = *((uint16_t*) ppp); pktLen = bswap_16(pktLen); if (pktLen > kMaxMsgLen) { fprintf(stderr, "YAP: ERROR packet length too large: %u > %d\n", pktLen, kMaxMsgLen); goto Detached; } // Get the packet data if (!readSocket(d->msgSocketFd, (char*) d->msgBuffer, pktLen)) { fprintf(stderr, "YAP: Failed to read packet data of length: %d\n", pktLen); goto Detached; } d->msgPacket->reset(); d->msgPacket->setReadTotalLength(pktLen); handleAsyncMessage(d->msgPacket); d->msgPacket->reset(); d->msgPacket->setReadTotalLength(0); return; Detached: serverDisconnected(); closeMsgSocket(); closeCmdSocket(); } }
// ======= FTP thread handler ========= static void _thread_ftp(void*inContext) { (void)inContext; fd_set readset, wrset; struct timeval_t t_val; int k; uint32_t timeout = 0; uint8_t recv_tmo = 0; t_val.tv_sec = 0; t_val.tv_usec = 5000; timeout = mico_get_time(); ftp_log("\r\n[FTP trd] FTP THREAD STARTED\r\n"); // *** First we have to get IP address and connect the cmd socket char pIPstr[16]={0}; int err; k = 3; do { err = gethostbyname((char *)pDomain4Dns, (uint8_t *)pIPstr, 16); if (err != kNoErr) { k--; mico_thread_msleep(50); } }while ((err != kNoErr) && (k > 0)); if ((err == kNoErr) && (ftpCmdSocket != NULL)) { ftpCmdSocket->addr.s_ip = inet_addr(pIPstr); ftpCmdSocket->clientFlag = NO_ACTION; free(pDomain4Dns); pDomain4Dns=NULL; // Connect socket! char ip[17]; memset(ip, 0x00, 17); inet_ntoa(ip, ftpCmdSocket->addr.s_ip); ftp_log("[FTP cmd] Got IP: %s, connecting...\r\n", ip); struct sockaddr_t *paddr = &(ftpCmdSocket->addr); int slen = sizeof(ftpCmdSocket->addr); // _micoNotify will be called if connected connect(ftpCmdSocket->socket, paddr, slen); } else { ftp_log("[FTP dns] Get IP error\r\n"); goto terminate; } if (recvBuf == NULL) { recvBuf = malloc(MAX_RECV_LEN+4); memset(recvBuf, 0, MAX_RECV_LEN+4); } recvLen = 0; // =========================================================================== // Main Thread loop while (1) { mico_thread_msleep(5); if (ftpCmdSocket == NULL) goto terminate; if ( ((mico_get_time() - timeout) > MAX_FTP_TIMEOUT) || (((mico_get_time() - timeout) > 8000) && (!(status & FTP_LOGGED))) ) { // ** TIMEOUT ** ftp_log("[FTP trd] Timeout\r\n"); timeout = mico_get_time(); if ((status & FTP_LOGGED)) ftpCmdSocket->clientFlag = REQ_ACTION_QUIT; else ftpCmdSocket->clientFlag = REQ_ACTION_DISCONNECT; } // ========== stage #1, Check cmd socket action requests =================== //REQ_ACTION_DISCONNECT if (ftpCmdSocket->clientFlag == REQ_ACTION_DISCONNECT) { ftpCmdSocket->clientFlag = NO_ACTION; closeDataSocket(); ftp_log("[FTP cmd] Socket disconnected\r\n"); if (ftpCmdSocket->disconnect_cb != LUA_NOREF) { queue_msg_t msg; msg.L = gL; msg.source = onFTP; msg.para1 = 0; msg.para2 = ftpCmdSocket->disconnect_cb; mico_rtos_push_to_queue( &os_queue, &msg, 0); } closeCmdSocket(0); continue; } //REQ_ACTION_QUIT if (ftpCmdSocket->clientFlag == REQ_ACTION_QUIT) { if ((status & FTP_LOGGED)) { ftpCmdSocket->clientFlag = NO_ACTION; ftp_log("[FTP cmd] Quit command\r\n"); if (_send("QUIT\r\n", 6) <= 0) { ftpCmdSocket->clientFlag = REQ_ACTION_DISCONNECT; } } else ftpCmdSocket->clientFlag = REQ_ACTION_DISCONNECT; continue; } if (!(status & FTP_CONNECTED)) continue; //-------------------------------------- //REQ_ACTION_LIST, REQ_ACTION_RECV, REQ_ACTION_SEND else if ((ftpCmdSocket->clientFlag == REQ_ACTION_LIST) || (ftpCmdSocket->clientFlag == REQ_ACTION_RECV) || (ftpCmdSocket->clientFlag == REQ_ACTION_SEND)) { ftpCmdSocket->clientLastFlag = ftpCmdSocket->clientFlag; ftpCmdSocket->clientFlag = NO_ACTION; _send("PASV\r\n", 6); } //REQ_ACTION_DOLIST else if (ftpCmdSocket->clientFlag == REQ_ACTION_DOLIST) { ftpCmdSocket->clientFlag = NO_ACTION; int res; if (ftpfile != NULL) { char tmps[100]; if (list_type == 1) sprintf(tmps,"NLST %s\r\n", ftpfile); else sprintf(tmps,"LIST %s\r\n", ftpfile); res = _send(&tmps[0], strlen(ftpfile)+7); free(ftpfile); ftpfile = NULL; } else { if (list_type == 1) res = _send("NLST\r\n", 6); else res = _send("LIST\r\n", 6); } if (res > 0) status |= FTP_LISTING; else { ftp_log("[FTP cmd] LIST command failed.\r\n"); } } //REQ_ACTION_DORECV else if (ftpCmdSocket->clientFlag == REQ_ACTION_DORECV) { ftpCmdSocket->clientFlag = NO_ACTION; char tmps[100]; sprintf(tmps,"RETR %s\r\n", ftpfile); int res = _send(&tmps[0], strlen(ftpfile)+7); if (res > 0) { status |= FTP_RECEIVING; file_status = 0; } else { ftp_log("[FTP cmd] RETR command failed.\r\n"); file_status = -4; } } //REQ_ACTION_DOSEND else if (ftpCmdSocket->clientFlag == REQ_ACTION_DOSEND) { ftpCmdSocket->clientFlag = NO_ACTION; char tmps[100]; if ((send_type & SEND_APPEND)) sprintf(tmps,"APPE %s\r\n", ftpfile); else sprintf(tmps,"STOR %s\r\n", ftpfile); int res = _send(&tmps[0], strlen(ftpfile)+7); if (res > 0) { file_status = 0; } else { ftp_log("[FTP cmd] STOR/APPE command failed.\r\n"); file_status = -4; } } //REQ_ACTION_CHDIR else if (ftpCmdSocket->clientFlag == REQ_ACTION_CHDIR) { ftpCmdSocket->clientFlag = NO_ACTION; if (ftpfile != NULL) { char tmps[100]; sprintf(tmps,"CWD %s\r\n", ftpfile); _send(&tmps[0], strlen(ftpfile)+6); free(ftpfile); ftpfile = NULL; } else { _send("PWD\r\n", 5); } } //REQ_ACTION_LOGGED else if (ftpCmdSocket->clientFlag == REQ_ACTION_LOGGED) { ftpCmdSocket->clientFlag=NO_ACTION; if (ftpCmdSocket->logon_cb != LUA_NOREF) { queue_msg_t msg; msg.L = gL; msg.source = onFTP; msg.para1 = 1; msg.para3 = NULL; msg.para2 = ftpCmdSocket->logon_cb; mico_rtos_push_to_queue( &os_queue, &msg, 0); } } //REQ_ACTION_LIST_RECEIVED else if (ftpCmdSocket->clientFlag == REQ_ACTION_LIST_RECEIVED) { ftpCmdSocket->clientFlag=NO_ACTION; if (ftpCmdSocket->list_cb != LUA_NOREF) { queue_msg_t msg; msg.L = gL; msg.source = onFTP; msg.para1 = recvDataLen; msg.para2 = ftpCmdSocket->list_cb; msg.para3 = (uint8_t*)malloc(recvDataLen+4); if (msg.para3 != NULL) memcpy((char*)msg.para3, recvDataBuf, recvDataLen); mico_rtos_push_to_queue( &os_queue, &msg, 0); } } //REQ_ACTION_RECEIVED else if (ftpCmdSocket->clientFlag == REQ_ACTION_RECEIVED) { ftpCmdSocket->clientFlag=NO_ACTION; if (ftpCmdSocket->received_cb != LUA_NOREF) { queue_msg_t msg; msg.L = gL; msg.source = onFTP; msg.para1 = file_status; msg.para3 = NULL; if (recv_type == RECV_TOSTRING) { msg.para3 = (uint8_t*)malloc(recvDataLen+4); if (msg.para3 != NULL) memcpy((char*)msg.para3, recvDataBuf, recvDataLen); } msg.para2 = ftpCmdSocket->received_cb; mico_rtos_push_to_queue( &os_queue, &msg, 0); } } //REQ_ACTION_SENT else if (ftpCmdSocket->clientFlag == REQ_ACTION_SENT) { ftpCmdSocket->clientFlag=NO_ACTION; if (ftpCmdSocket->sent_cb != LUA_NOREF) { queue_msg_t msg; msg.L = gL; msg.source = onFTP; msg.para1 = file_status; msg.para3 = NULL; msg.para2 = ftpCmdSocket->sent_cb; mico_rtos_push_to_queue( &os_queue, &msg, 0); } } // ========== stage 2, check data send ===================================== if ((ftpDataSocket != NULL) && ((status & FTP_SENDING))) { FD_ZERO(&wrset); FD_SET(ftpDataSocket->socket, &wrset); // check socket state select(ftpDataSocket->socket+1, NULL, &wrset, NULL, &t_val); if (FD_ISSET(ftpDataSocket->socket, &wrset)) { int err; if ((send_type & SEND_STRING)) err = _sendString(); else err = _sendFile(); if (err != 0) { closeDataSocket(); // close file; if (file_fd != FILE_NOT_OPENED) { SPIFFS_close(&fs,file_fd); file_fd = FILE_NOT_OPENED; ftp_log("\r\n[FTP dta] Data file closed\r\n"); } data_done = 1; status &= ~FTP_SENDING; ftpCmdSocket->clientFlag = REQ_ACTION_SENT; } continue; } } // ========== stage 3, check receive&disconnect ============================ FD_ZERO(&readset); // ** select sockets to monitor for receive or disconnect int maxfd = ftpCmdSocket->socket; FD_SET(ftpCmdSocket->socket, &readset); if ( (ftpDataSocket != NULL) && ((status & FTP_DATACONNECTED)) ) { if (ftpDataSocket->socket > maxfd) maxfd = ftpDataSocket->socket; FD_SET(ftpDataSocket->socket, &readset); } // ** check sockets state select(maxfd+1, &readset, NULL, NULL, &t_val); // ** Check COMMAND socket if (FD_ISSET(ftpCmdSocket->socket, &readset)) { // read received data to buffer int rcv_len; if ((MAX_RECV_LEN-recvLen) > 1) { rcv_len = recv(ftpCmdSocket->socket, (recvBuf+recvLen), MAX_RECV_LEN-recvLen-1, 0); } else { // buffer full, ignore received bytes char tmpb[16]; rcv_len = recv(ftpCmdSocket->socket, &tmpb[0], 16, 0); } if (rcv_len <= 0) { // failed ftp_log("\r\n[FTP cmd] Disconnect!\r\n"); ftpCmdSocket->clientFlag = REQ_ACTION_DISCONNECT; continue; } recvLen += rcv_len; _checkCmdResponse(); // leave only the last line in buffer timeout = mico_get_time(); recv_tmo = 0; } // ** Check DATA socket if ( (ftpDataSocket != NULL) && ((status & FTP_DATACONNECTED)) ) { if (FD_ISSET(ftpDataSocket->socket, &readset)) { // read received data to buffer int rcv_len = recv(ftpDataSocket->socket, (recvDataBuf+recvDataLen), max_recv_datalen-recvDataLen-1, 0); if (rcv_len <= 0) { // failed if (!(status & (FTP_RECEIVING | FTP_LISTING))) { ftp_log("\r\n[FTP dta] Disconnect!\r\n"); closeDataSocket(); file_status = -9; data_done = 1; } continue; } else { if ((status & FTP_RECEIVING) && (recv_type == RECV_TOFILE)) { // === write received data to file === recvDataLen = rcv_len; _saveData(0); recvDataLen = 0; } else if ((status & FTP_LISTING) || ((status & FTP_RECEIVING) && (recv_type == RECV_TOSTRING))) { if ((recvDataLen + rcv_len) < (max_recv_datalen-16)) recvDataLen += rcv_len; else recvDataLen = max_recv_datalen-16; *(recvDataBuf + recvDataLen) = '\0'; } } timeout = mico_get_time(); recv_tmo = 0; } } // ===== nothing received ================================================== recv_tmo++; if (recv_tmo < 10) continue; recv_tmo = 0; // == Check if something was received from Command socket == if (recvLen > 0) { // == Analize response === response(); recvLen = 0; memset(recvBuf, 0, MAX_RECV_LEN); } // == Check if Data socket was receiving == if ((status & (FTP_RECEIVING | FTP_LISTING))) { // Finish all operattions on data socket if ((status & FTP_RECEIVING) && (recv_type == RECV_TOFILE)) { _saveData(1); recvDataLen = 0; } else { if ((status & FTP_RECEIVING) && (recv_type == RECV_TOSTRING)) { file_status = recvDataLen; } ftp_log("[FTP dta] Data received (%d)\r\n", recvDataLen); } if ((status & FTP_LISTING)) { status &= ~FTP_LISTING; ftpCmdSocket->clientFlag = REQ_ACTION_LIST_RECEIVED; } if ((status & FTP_RECEIVING)) { status &= ~FTP_RECEIVING; ftpCmdSocket->clientFlag = REQ_ACTION_RECEIVED; } // Close data socket closeDataSocket(); data_done = 1; } } // while terminate: _ftp_deinit(0); ftp_log("\r\n[FTP trd] FTP THREAD TERMINATED\r\n"); ftp_thread_is_started = false; mico_rtos_delete_thread( NULL ); }