Dependencies: XBeeLib mbed HvZAlphaNumLib HvZServerLib
lib/udp.cpp
- Committer:
- etherealflaim
- Date:
- 2010-12-12
- Revision:
- 1:d1b5cd8b2c18
- Parent:
- 0:9cdba0589ba2
File content as of revision 1:d1b5cd8b2c18:
#include "mbed.h" #include "iHvZ.hpp" #include "if/net/netudpsocket.h" #include "udp.hpp" UDP::UDP(iHvZ *game, PinName eth_in) : m_game(game), m_eth(eth_in), m_eth_int(eth_in), m_pNetUdpSocket(NULL), m_pCbItem(NULL), m_pCbMeth(NULL), m_pCb(NULL), //conn(IpAddr(192,168,1,2),IpAddr(255,255,255,0), IpAddr(), IpAddr()) { // Set the game ID char mac[8]; char macaddr[12+1]; eth.address(mac); sprintf(macaddr, "%02X%02X%02X%02X%02X%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); m_game->id(macaddr); //m_eth_int.rise(this, &UDP::check); m_eth_chk.attach(this, &UDP::check, 5); registered = 0; } UDP::~UDP() { close(); } void UDP::check() { // debounce (if attached to a button) wait(.1); //if (m_eth) //{ // usb.printf("- Connection found, starting sync\r\n"); ethlink(); //} m_eth_chk.attach(this, &UDP::check, 10); } int UDP::sendto(const char* buf, int len, Host* pHost) { UDPErr udpSocketErr = checkInst(); if(udpSocketErr) return udpSocketErr; return m_pNetUdpSocket->sendto(buf, len, pHost); } int UDP::recvfrom(char* buf, int len, Host* pHost) { UDPErr udpSocketErr = checkInst(); if(udpSocketErr) return udpSocketErr; return m_pNetUdpSocket->recvfrom(buf, len, pHost); } UDPErr UDP::close() { if(!m_pNetUdpSocket) return UDPSOCKET_SETUP; m_pNetUdpSocket->resetOnEvent(); UDPErr udpSocketErr = (UDPErr) m_pNetUdpSocket->close(); //Close (can already be closed) Net::releaseUdpSocket(m_pNetUdpSocket); //And release it so it can be freed when properly removed m_pNetUdpSocket = NULL; return udpSocketErr; } void UDP::ethlink() { Serial usb(USBTX,USBRX); usb.printf("Checking for Ethernet connection...\r\n"); Host game_server(IpAddr(128, 61, 89, 71), HVZ_PORT, HVZ_HOSTNAME); //Host game_server(IpAddr(192, 168, 1, 1), HVZ_PORT, HVZ_HOSTNAME); /* Function to call upon Server response */ setOnEvent(this, &UDP::read); if( !eth.link() ) return; usb.printf(" - Link active\r\n"); m_game->alphanumdisplay_device().display('*'); if( registered == 0 ) { conn.setup(); //Get the MAC address of this device eth.address((char *)mac.octet); // Send to Game Server until receive a response // and wait for a response do { register_device(mac, &game_server); wait(0.1); Net::poll(); } while ( memcmp("i",&(srvr_resp[0]),1) ); printf("srvr_resp = %s\r\n", srvr_resp); // If the response is an acknowledgement // get the IDs from the response and // set the game device and tag IDs if( get_ack_err(srvr_resp,HVZ_REG) ) { set_ids(srvr_resp); //printf( "deviceID = %s\r\n", m_game->id() ); //printf( "tagID = %s\r\n", m_game->tagid() ); // Clear the response string memset(srvr_resp,0,sizeof(srvr_resp)); // Upon registration there will be no tags or // updates for this device, so just return here return; } // Set as already registered registered = 1; // Clear the response string memset(srvr_resp,0,sizeof(srvr_resp)); } // Submit any tags to the server // and wait for a response do { send_tag(&game_server, m_game->get_victims()); wait(0.1); Net::poll(); //} while ( memcmp("i",&(srvr_resp[0]),1) ); } while ( 'i' != srvr_resp[0] ); printf("srvr_resp = %s\r\n", srvr_resp); // On successfully reporting tags to Server // clear the tagged list if( get_ack_err(srvr_resp,HVZ_TAG) ) m_game->clear_victims(); // Clear the response string memset(srvr_resp,0,sizeof(srvr_resp)); // Next request updates to the server do { // If the deviceID is set at update request send_pull(&game_server); wait(0.1); Net::poll(); //} while ( !srvr_resp[0] ); } while ( 'i' != srvr_resp[0] ); printf("srvr_resp = %s\r\n", srvr_resp); // If pull request ack, update settings of the game if( get_ack_err(srvr_resp,HVZ_PULL) ) update_settings(srvr_resp); // Clear the response string memset(srvr_resp,0,sizeof(srvr_resp)); // Display a completion mark m_game->alphanumdisplay_device().display('^'); wait(1); m_game->alphanumdisplay_device().display(m_game->status()==STATUS_HUMAN?'H':'Z'); } void UDP::read(UDPSocketEvent e) { Host host(IpAddr(128, 61, 89, 71), HVZ_PORT, HVZ_HOSTNAME); //Host host(IpAddr(192, 168, 1, 1), HVZ_PORT, HVZ_HOSTNAME); if ( e == UDPSOCKET_READABLE ) { while( int len = recvfrom(srvr_resp, sizeof(srvr_resp), &host) ) { if( len <= 0 ) break; } } } void UDP::set_ids(char *response) { char buf[9]; /* First set the deviceID */ memcpy(buf,response+13,8); buf[8] = '\0'; m_game->id(buf); /* Next set the tagID */ memcpy(buf,response+22,8); buf[8] = '\0'; m_game->life(buf); m_game->save(); } void UDP::update_settings(char *response) { char *tok; // Clear the lives so we can add them all back m_game->clear_lives(); // Start tokenizing the response tok = strtok(response,"\001"); typedef enum { RNONE,RDEV,RLIVES,RSTUN,RINC } readtype; readtype type = RNONE; while (tok != NULL) { //printf ("%s\r\n",tok); tok = strtok (NULL, "\001"); if( strcmp(tok,"deviceid") == 0 ) { type = RDEV; continue; } else if( strcmp(tok,"tagids") == 0 ) { type = RLIVES; continue; } else if( strcmp(tok,"stuntime") == 0 ) { type = RSTUN; continue; } else if( strcmp(tok,"incubate") == 0 ) { type = RINC; continue; } switch (type) { case RDEV: m_game->id(tok); break; case RLIVES: m_game->life(tok); continue; // possibility of more than one case RSTUN: m_game->stun_duration((unsigned)atoi(tok)); break; case RINC: m_game->incubation_time((unsigned)atoi(tok)); break; } // go back to no parsing type = RNONE; } m_game->save(); } void UDP::send_pull(Host *host) { char data[64]; // char buff[12]; // // memset(data,0,sizeof(data)); // if( type == PULL_DEV ) // sprintf(buff, "%c%c%c%c%c%c%c%c", pullId[0], pullId[1], pullId[2], // pullId[3], pullId[4], pullId[5], pullId[6], pullId[7]); // else // sprintf(buff, "%02X%02X%02X%02X%02X%02X", pullId[0], pullId[1], pullId[2], // pullId[3], pullId[4], pullId[5]); // strcat(data, "iHvZ\001pull\001"); // strcat(data, buff); // strcat(data, "\001end"); sprintf(data, "iHvZ\001pull\001%s\001end", m_game->id().c_str()); sendto(data, strlen(data), host); } inline void UDP::send_tag(Host *host, vector<string> taggedIDs) { int totalsize = 32; for (int i = 0; i < taggedIDs.size(); i++) { totalsize += taggedIDs[i].size(); } char tmp[totalsize]; // Clear out buffers memset(tmp, 0, sizeof(tmp)); // Append tagIDs for (int i = 0; i < taggedIDs.size(); i++) { strcat(tmp, taggedIDs[i].c_str()); strcat(tmp, "\001"); } string tagids = tmp; sprintf(tmp, "iHvZ\001tag\001%s\001%send", m_game->id().c_str(), tagids.c_str()); sendto(tmp, strlen(tmp), host); } void UDP::resetOnEvent() //Disable callback { m_pCb = NULL; m_pCbItem = NULL; m_pCbMeth = NULL; } void UDP::onNetUdpSocketEvent(NetUdpSocketEvent e) { if(m_pCbItem && m_pCbMeth) (m_pCbItem->*m_pCbMeth)((UDPSocketEvent) e); else if(m_pCb) m_pCb((UDPSocketEvent) e); } UDPErr UDP::checkInst() { if(!m_pNetUdpSocket) { m_pNetUdpSocket = Net::udpSocket(); if(!m_pNetUdpSocket) { return UDPSOCKET_IF; //Interface did not return a socket (usually because a default interface does not exist) } m_pNetUdpSocket->setOnEvent(this, &UDP::onNetUdpSocketEvent); } return UDPSOCKET_OK; }