int GSMClient::read(uint8_t *buf, size_t size) { return internalRead(buf, size, false); }
GpioState GpioPlateformImplementation::read() { return internalRead(); }
int GSMClient::readln(uint8_t *buf, size_t size) { return internalRead(buf, size, true); }
void Connection::executeNetwork() { switch(m_state){ case STATE_INIT: { //Resolve host m_ip = inet_addr(m_host.c_str()); if(m_ip == INADDR_NONE){ struct hostent* hp = gethostbyname(m_host.c_str()); if(hp != NULL){ if(hp->h_addrtype == AF_INET){ //only are supported ipv4 addr m_ip = *(uint32_t*)hp->h_addr_list[0]; } else{ closeConnectionError(ERROR_WRONG_HOST_ADDR_TYPE); return; } } else{ closeConnectionError(ERROR_CANNOT_RESOLVE_HOST); return; } } //Create a TCP socket m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); #ifdef WIN32 if(m_socket == INVALID_SOCKET){ closeConnectionError(ERROR_CANNOT_CREATE_SOCKET); return; } #else if(m_socket <= 0){ m_socket = INVALID_SOCKET; closeConnectionError(ERROR_CANNOT_CREATE_SOCKET); return; } #endif //Set non-blocking socket #ifdef WIN32 unsigned long mode = 1; if(ioctlsocket(m_socket, FIONBIO, &mode) == SOCKET_ERROR){ closeConnectionError(ERROR_CANNOT_SET_NOBLOCKING_SOCKET); return; } #else if(fcntl(m_socket, F_SETFL, O_NONBLOCK) == -1){ closeConnectionError(ERROR_CANNOT_SET_NOBLOCKING_SOCKET); return; } #endif //Reset traffic counter m_sentBytes = 0; m_recvBytes = 0; //And connect sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = m_ip; addr.sin_port = htons(m_port); int ret = connect(m_socket, (sockaddr*)&addr, sizeof(addr)); if(ret == SOCKET_ERROR && getSocketError() != CONNECT_WOULD_BLOCK){ closeConnectionError(ERROR_CANNOT_CONNECT); return; } else if(ret == 0){ //connection succeeds m_state = STATE_CONNECTED; } else{ //waiting non blocking connect m_state = STATE_CONNECTING; m_ticks = SDL_GetTicks(); } break; } case STATE_CONNECTING: { //Check socket state timeval tv = {0, 0}; //non-blocking select fd_set write_set; FD_ZERO(&write_set); FD_SET(m_socket, &write_set); int ret = select(m_socket + 1, NULL, &write_set, NULL, &tv); if(ret == 0){ //time expired, socket not connected yet if(SDL_GetTicks() - m_ticks > 20*1000){ //waiting 20 seconds? -> timeout closeConnectionError(ERROR_CONNECT_TIMEOUT); } } else if(ret == 1 && FD_ISSET(m_socket, &write_set)){ #ifndef WINCE //Check if it was a successful connection int optError; optlen_t optErrorLen = sizeof(optError); int ret = getsockopt(m_socket, SOL_SOCKET, SO_ERROR, (opt_t*)&optError, &optErrorLen); if(ret != SOCKET_ERROR && optError == 0){ //connection succeeded m_state = STATE_CONNECTED; // record starts now if(g_recordfilename.size()) { m_recordstart=SDL_GetTicks(); m_recordfile=yatc_fopen(g_recordfilename.c_str(),"wb"); } //raise onConnect event m_protocol->onConnect(); } else if(ret != SOCKET_ERROR && optError != 0){ //connection failed closeConnectionError(ERROR_UNSUCCESSFUL_CONNECTION); } else{ //call to getsockopt failed closeConnectionError(ERROR_GETSOCKTOPT_FAIL); } #else // Since Windows Mobile 2003 (WINCE4.20) seems to set 120 in WSAGetLastError() which stands for something // like CALLNOTIMPLEMENTED we'll just stub this to successful connection and pray it works ;) DEBUGPRINT(DEBUGPRINT_LEVEL_OBLIGATORY, DEBUGPRINT_NORMAL, "WINCE Connection\n"); m_state = STATE_CONNECTED; m_protocol->onConnect(); #endif } else if(ret == SOCKET_ERROR){ //select failed closeConnectionError(ERROR_SELECT_FAIL_CONNECTING); } else{ //should not reach this point closeConnectionError(ERROR_UNEXPECTED_SELECT_RETURN_VALUE); } break; } case STATE_CONNECTED: { //Try to read messages while(m_state == STATE_CONNECTED && getPendingInput() > 0){ switch(m_readState){ case READING_SIZE: { int ret = internalRead(2, true); if(ret != 2){ checkSocketReadState(); return; } if(!m_inputMessage.getU16(m_msgSize)){ printf("Failed reading msg size\n"); closeConnectionError(ERROR_UNEXPECTED_RECV_ERROR); return; } if(m_msgSize > NETWORK_MESSAGE_SIZE){ closeConnectionError(ERROR_TOO_BIG_MESSAGE); return; } } case READING_CHECKSUM: { if(m_checksumEnable){ m_readState = READING_CHECKSUM; int ret = internalRead(4, true); if(ret != 4){ checkSocketReadState(); return; } uint32_t checksum; if(!m_inputMessage.getU32(checksum)){ printf("Failed reading checksum\n"); closeConnectionError(ERROR_UNEXPECTED_RECV_ERROR); return; } else { m_msgSize-=4; m_readState = READING_MESSAGE; } } else m_readState = READING_MESSAGE; } case READING_MESSAGE: { int ret = internalRead(m_msgSize, false); if(ret <= 0){ checkSocketReadState(); return; } else if(ret != m_msgSize){ m_msgSize -= ret; checkSocketReadState(); return; } //decrypt incoming message if needed if(m_cryptoEnable && m_crypto){ if(!m_crypto->decrypt(m_inputMessage)){ closeConnectionError(ERROR_DECRYPT_FAIL); return; } } else if(!m_cryptoEnable) { m_inputMessage.setReadPos(2); } else { // this is 8.41 specific // data in unencrypted packets is now including unencrypted length, // + encrypted length ... although packet is not encrypted // let's just cut the cr/\p /*uint16_t size = */m_inputMessage.getU16(); } if(m_recordfile) { uint32_t timestamp=SDL_GetTicks()-m_recordstart; uint16_t size=m_inputMessage.getReadSize(); fwrite(×tamp, 4, 1, m_recordfile); fwrite(&size,2,1,m_recordfile); fwrite(m_inputMessage.getReadBuffer(), m_inputMessage.getReadSize(), 1, m_recordfile); fflush(m_recordfile); } //raise onRecv event if(!m_protocol->onRecv(m_inputMessage)){ closeConnectionError(ERROR_PROTOCOL_ONRECV); return; } //resets input message state m_readState = READING_SIZE; m_inputMessage.reset(); break; } } } checkSocketReadState(); break; } case STATE_CLOSED: case STATE_ERROR: //nothing to do break; } }