#include <winsock2.h> #include <winsock.h> #include <ws2tcpip.h> #include <stdio.h> #include <windows.h> #include <iostream> #include "network.h" #include <stdlib.h> #include "error.h" #define ERROR_STR "Network communication error: " #define ERROR_STR_END " - Consult www.msdn.microsoft.com" #define DEFALT_PASSWORD "LEGOCLIENT" #define MAX_PASSWORD_LENGTH 10 #define TIMEOUT 3000 //****************************************************************************************************** //if you get a compile error with "undefined reference to WSAStartup...." remember to link to libwsock32 //In code blocks: project->build option->linker setting->add - and then locate the libwsock32.a file //In other compilers you might be able to use #pragma comment(lib, "wsock32.lib") or something simular //******************************************************************************************************* unsigned int network_send(SOCKET *this_socket, unsigned char *this_buffer, unsigned int length){ return send(*this_socket, (char *) this_buffer, length, 0); //Send "Hello server" } unsigned int network_connect(SOCKET *this_socket, sockaddr_in *this_sockadd_in){ return connect( *this_socket, (sockaddr*) this_sockadd_in, sizeof(*this_sockadd_in)); } Nxt_network::Nxt_network(){ } Nxt_network::~Nxt_network(){ disconnect(); }; void Nxt_network::send(unsigned char *buffer, unsigned int num_bytes){ /*unsigned int i; i=0; while(i<num_bytes){ printf("\nSend Buffer[%d]=0x%x\n", i, buffer[i]); i++; }*/ int send_bytes = network_send(&this->my_sock, buffer, num_bytes); //printf("Send bytes: %d\n", send_bytes); if(send_bytes == -1 || (unsigned int) send_bytes != num_bytes ){ string s; s = this->error_to_string(WSAGetLastError()); throw Nxt_exception::Nxt_exception("send", "Nxt_network", NETWORK_COM_ERROR, s); } return; } void Nxt_network::connect(unsigned int port, string ip_add, Server_settings &settings, string password){ unsigned char buffer[MAX_PASSWORD_LENGTH+1]; unsigned short int pass_len, i; unsigned char answer[5]; struct timeval timeout; timeout.tv_sec = TIMEOUT; timeout.tv_usec = 0; ws_ver=MAKEWORD(2, 0); // winsock 2.0 ws_status=WSAStartup(ws_ver, &ws_data); if(ws_status != 0){ string s; s = this->error_to_string(WSAGetLastError()); throw Nxt_exception::Nxt_exception("connect", "Nxt_network", NETWORK_COM_ERROR, s); } this->my_sock=socket(AF_INET, SOCK_STREAM, 0); if(my_sock == INVALID_SOCKET){ string s; s = this->error_to_string(WSAGetLastError()); throw Nxt_exception::Nxt_exception("connect", "Nxt_network", NETWORK_COM_ERROR, s); } sockaddr_in sock_in; sock_in.sin_port=htons(port); sock_in.sin_addr.s_addr=inet_addr(ip_add.c_str()); sock_in.sin_family=AF_INET; if(setsockopt(my_sock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout)) == -1){ string s; s = this->error_to_string(WSAGetLastError()); throw Nxt_exception::Nxt_exception("connect", "Nxt_network", NETWORK_COM_ERROR, s); } if(network_connect(&this->my_sock,&sock_in)){ string s; s = this->error_to_string(WSAGetLastError()); throw Nxt_exception::Nxt_exception("send", "Nxt_network", NETWORK_COM_ERROR, s); } if(password.empty()){ password=DEFALT_PASSWORD; } pass_len = password.length(); if(pass_len > MAX_PASSWORD_LENGTH){ pass_len = MAX_PASSWORD_LENGTH; } i=0; while(i <pass_len){ buffer[i] = password[i]; i++; } while(i < MAX_PASSWORD_LENGTH+1){ buffer[i] = '\0'; i++; } send(buffer,MAX_PASSWORD_LENGTH+1); receive(answer, 9); if(answer[4]){ throw Nxt_exception::Nxt_exception("connect", "Nxt_network", answer[4] & 0xff); } settings.mode = (Server_mode) answer[3]; settings.timeout = (0xff & answer[5]) | ((0xff & answer[6]) << 8)| ((0xff & answer[7]) << 16)| ((0xff & answer[8]) << 24); return; } void Nxt_network::disconnect(){ Sleep(2000); WSACleanup(); closesocket(my_sock); return; } void Nxt_network::receive(unsigned char *buffer, unsigned int length){ int get_bytes = recv(my_sock, (char *) buffer, length, 0); if( get_bytes == -1){ string s; s = this->error_to_string(WSAGetLastError()); throw Nxt_exception::Nxt_exception("send", "Nxt_network", NETWORK_COM_ERROR, s); } if(get_bytes == 0 && length !=0){ //hack to avoid that when the client is thrown off //a wrong error message might be thrown if the client pools the server for a message if(length >= 5){ buffer[4] = 0x00; } } //the server will send these bytes if case of an error //if( buffer[4] <= (unsigned char) NETWORK_ERROR_HIGH && buffer[4] >= (unsigned char) NETWORK_ERROR_LOW ){ // throw Nxt_exception::Nxt_exception("receive", "Nxt_network", buffer[4] & 0xff); //} return; } //does nothing void Nxt_network::flush(){ return; } Connection_type Nxt_network::get_type(){ return NXT_NETWORK; } std::string Nxt_network::error_to_string(int err){ string s; char *error_s; if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &error_s, 0, NULL)){ std::stringstream error_string; error_string << ERROR_STR << WSAGetLastError() << ERROR_STR_END; s = error_string.str(); return s; } s = error_s; //free(error_s); return s; }