/*************************************************************************** udpnet.cpp - Basic UDP/IP functionality ------------------- begin : ma jan 17 2005 copyright : (C) 2005 by CJP email : cornware-cjp@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include #include /* Watch out with netinet/in.h: it contains definitions of ntohl etc., and it should, but they conflict with other declarations in system headers on some systems. */ #include #include #include #include #include #include #include "udpnet.h" CUDPNet::CUDPNet(unsigned int port) { m_SendCounter = 0; m_Socket = socket(AF_INET,SOCK_DGRAM,0); if(m_Socket < 0) { printf("Cannot open socket\n"); return; } int enable = 1; if(setsockopt(m_Socket, SOL_SOCKET, SO_BROADCAST, &enable, sizeof(int)) != 0) { printf("Cannot use broadcast mode\n"); close(m_Socket); m_Socket = -1; return; } // bind to port struct sockaddr_in MyAddress; MyAddress.sin_family = AF_INET; MyAddress.sin_addr.s_addr = htonl(INADDR_ANY); MyAddress.sin_port = htons(port); int rc = bind (m_Socket, (struct sockaddr *) &MyAddress, sizeof(MyAddress)); if(rc < 0) { printf("cannot bind port number %d \n", port); close(m_Socket); m_Socket = -1; return; } fcntl(m_Socket, F_SETFL, O_NONBLOCK); printf("Connected on port %d\n", port); } CUDPNet::~CUDPNet() { closeConnection(); } void CUDPNet::closeConnection() { if(m_Socket >= 0) close(m_Socket); m_Socket = -1; printf("Disconnected\n"); } bool CUDPNet::isConnected() { return m_Socket >= 0; } bool CUDPNet::receiveData(unsigned int millisec) { if(m_Socket < 0) return false; // Watch socket to see when it has input. struct pollfd pfd; pfd.fd = m_Socket; pfd.events = POLLIN; poll(&pfd, 1, millisec); if ((pfd.revents & POLLIN) == 0) { //printf("poll() says: no data on socket \n"); return false; } //DO NOT clear the data!!! //m_ReceivedData.clear(); struct sockaddr_in caddr; socklen_t clen = sizeof(caddr); int len = 4096; //just for testing purposes. TODO: scan for MTU size (man ip(7)) Uint8 buffer[len]; //Receive: while(true) { // receive message int n = recvfrom(m_Socket, (NETTYPE *)buffer, len, 0, (struct sockaddr *) &caddr, &clen); if(n < 0) //nothing received break; CIPNumber ipnum; ipnum = caddr.sin_addr.s_addr; int portnr = ntohs(caddr.sin_port); CBinBuffer binbuffer; for(unsigned int i=0; i < (unsigned int)n; i++) binbuffer.push_back(Uint8(buffer[i])); m_ReceiveBuffer.push_back(CMessageBuffer()); CMessageBuffer &msgbuf = m_ReceiveBuffer.back(); msgbuf.setBuffer(binbuffer); msgbuf.setIP(ipnum); msgbuf.setPort(portnr); } return true; } bool CUDPNet::sendData(CMessageBuffer &data) { if(m_Socket < 0) return false; //printf("Sending %s\n", data.dump().c_str()); data.setCounter(m_SendCounter); m_SendCounter++; CIPNumber ipnum = data.getIP(); Uint8 num8[4]; for(unsigned int i=0; i<4; i++) num8[i] = ipnum[i]; Uint32 num32 = *((Uint32 *)num8); //printf("Sending to %d.%d.%d.%d port %d\n", num8[0], num8[1], num8[2], num8[3], data.getPort()); struct in_addr a; a.s_addr = num32; struct sockaddr_in remoteCliAddr; remoteCliAddr.sin_family = AF_INET; remoteCliAddr.sin_addr = a; remoteCliAddr.sin_port = htons(data.getPort()); unsigned int len = data.size(); Uint8 buffer[len]; for(unsigned int i=0; i < len; i++) buffer[i] = data[i]; int rc = sendto(m_Socket, (NETTYPE *)buffer, len,0 , (struct sockaddr *) &remoteCliAddr, sizeof(remoteCliAddr)); return (rc >= 0); } CIPNumber getBroadcastAddress() { CIPNumber ret; ret = INADDR_BROADCAST; printf("Broadcast address is %s\n", ret.toString().c_str()); return ret; }