]> git.vomp.tv Git - vompserver.git/blob - dsock.c
Bootp server
[vompserver.git] / dsock.c
1 /*
2     Copyright 2004-2005 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "dsock.h"
22
23 DatagramSocket::DatagramSocket()
24 {
25   addrlen = sizeof(struct sockaddr);
26   log = Log::getInstance();
27   initted = 0;
28 }
29
30 DatagramSocket::~DatagramSocket()
31 {
32   shutdown();
33 }
34
35 bool DatagramSocket::init(short port)
36 {
37   myPort = port;
38   if ((socketnum = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
39   {
40     log->log("UDP", Log::CRIT, "Socket error");
41     return false;
42   }
43
44   myAddr.sin_family = AF_INET;         // host byte order
45   myAddr.sin_port = htons(myPort);     // short, network byte order
46   myAddr.sin_addr.s_addr = INADDR_ANY; // auto-fill with my IP
47   memset(&(myAddr.sin_zero), 0, 8);    // zero the rest of the struct
48   if (bind(socketnum, (struct sockaddr *)&myAddr, addrlen) == -1)
49   {
50     log->log("UDP", Log::CRIT, "Bind error");
51     close(socketnum);
52     return false;
53   }
54
55   int allowed = 1;
56   setsockopt(socketnum, SOL_SOCKET, SO_BROADCAST, &allowed, sizeof(allowed));
57
58   FD_ZERO(&readfds);
59   FD_SET(socketnum, &readfds);
60   tv.tv_sec = 0;
61   tv.tv_usec = 0;
62
63   initted = 1;
64   return true;
65 }
66
67 void DatagramSocket::shutdown()
68 {
69   if (initted) close(socketnum);
70   initted = 0;
71 }
72
73 unsigned char DatagramSocket::waitforMessage(unsigned char how)
74 {
75   if (!initted) return 0;
76
77   /* how = 0 - block
78      how = 1 - start new wait
79      how = 2 - continue wait
80   */
81
82   struct timeval* passToSelect = NULL;
83
84
85   if (how == 0)
86   {
87     passToSelect = NULL;
88   }
89   else if (how == 1)
90   {
91     tv.tv_sec = 1;
92     tv.tv_usec = 100000;
93     passToSelect = &tv;
94   }
95   else if (how == 2)
96   {
97     if ((tv.tv_sec == 0) && (tv.tv_usec == 0))  // protection in case timer = 0
98     {
99       tv.tv_sec = 1;
100       tv.tv_usec = 100000;
101     }
102     passToSelect = &tv;
103   }
104   FD_ZERO(&readfds);
105   FD_SET(socketnum, &readfds);
106
107   if (select(socketnum + 1, &readfds, NULL, NULL, passToSelect) <= 0) return 1;
108
109   if ((mlength = recvfrom(socketnum, buf, MAXBUFLEN, 0, (struct sockaddr *)&theirAddr, &addrlen)) == -1)
110   {
111     log->log("UDP", Log::DEBUG, "recvfrom error");
112     return 0;
113   }
114   else
115   {
116     memset(&buf[mlength], 0, MAXBUFLEN - mlength);
117     strcpy(fromIPA, inet_ntoa(theirAddr.sin_addr));
118     fromPort = ntohs(theirAddr.sin_port);
119     log->log("UDP", Log::DEBUG, "%s:%i received length %i", fromIPA, fromPort, mlength);
120     return 2;
121   }
122
123   /* Return 0, failure
124      Return 1, nothing happened, timer expired
125      Return 2, packet arrived (timer not expired)
126   */
127 }
128
129 int DatagramSocket::getDataLength(void) const
130 {
131   return mlength;
132 }
133
134 char *DatagramSocket::getData(void)             {  return buf;  }
135 char *DatagramSocket::getFromIPA(void)          {  return fromIPA;  }
136 short DatagramSocket::getFromPort(void) const   {  return fromPort; }
137
138 void DatagramSocket::send(char *ipa, short port, char *message, int length)
139 {
140   int sentLength = 0;
141
142   theirAddr.sin_family = AF_INET;      // host byte order
143   theirAddr.sin_port = htons(port);    // short, network byte order
144   struct in_addr tad;                  // temp struct tad needed to pass to theirAddr.sin_addr
145   tad.s_addr = inet_addr(ipa);
146   theirAddr.sin_addr = tad;            // address
147   memset(&(theirAddr.sin_zero), 0, 8); // zero the rest of the struct
148
149   sentLength = sendto(socketnum, message, length, 0, (struct sockaddr *)&theirAddr, addrlen);
150   if (sentLength == length)
151   {
152     log->log("UDP", Log::DEBUG, "%s:%i sent length %i", ipa, port, length);
153     return;
154   }
155
156   log->log("UDP", Log::DEBUG, "%s:%i send failed %i", ipa, port, length);
157
158   sentLength = sendto(socketnum, message, length, 0, (struct sockaddr *)&theirAddr, addrlen);
159   if (sentLength == length)
160   {
161     log->log("UDP", Log::DEBUG, "%s:%i sent length %i 2nd try", ipa, port, length);
162     return;
163   }
164
165   log->log("UDP", Log::DEBUG, "%s:%i send failed %i 2nd try", ipa, port, length);
166 }
167