00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #include "hdhomerun.h"
00049 #include <windows.h>
00050 #include <iphlpapi.h>
00051
00052 int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int max_count)
00053 {
00054 PIP_ADAPTER_INFO AdapterInfo;
00055 ULONG AdapterInfoLength = sizeof(IP_ADAPTER_INFO) * 16;
00056
00057 while (1) {
00058 AdapterInfo = (IP_ADAPTER_INFO *)malloc(AdapterInfoLength);
00059 if (!AdapterInfo) {
00060 return -1;
00061 }
00062
00063 ULONG LengthNeeded = AdapterInfoLength;
00064 DWORD Ret = GetAdaptersInfo(AdapterInfo, &LengthNeeded);
00065 if (Ret == NO_ERROR) {
00066 break;
00067 }
00068
00069 free(AdapterInfo);
00070
00071 if (Ret != ERROR_BUFFER_OVERFLOW) {
00072 return -1;
00073 }
00074 if (AdapterInfoLength >= LengthNeeded) {
00075 return -1;
00076 }
00077
00078 AdapterInfoLength = LengthNeeded;
00079 }
00080
00081 int count = 0;
00082 PIP_ADAPTER_INFO Adapter = AdapterInfo;
00083 while (Adapter) {
00084 IP_ADDR_STRING *IPAddr = &Adapter->IpAddressList;
00085 while (IPAddr) {
00086 uint32_t ip_addr = ntohl(inet_addr(IPAddr->IpAddress.String));
00087 uint32_t subnet_mask = ntohl(inet_addr(IPAddr->IpMask.String));
00088
00089 if (ip_addr == 0) {
00090 IPAddr = IPAddr->Next;
00091 continue;
00092 }
00093
00094 struct hdhomerun_local_ip_info_t *ip_info = &ip_info_list[count++];
00095 ip_info->ip_addr = ip_addr;
00096 ip_info->subnet_mask = subnet_mask;
00097
00098 if (count >= max_count) {
00099 break;
00100 }
00101
00102 IPAddr = IPAddr->Next;
00103 }
00104
00105 if (count >= max_count) {
00106 break;
00107 }
00108
00109 Adapter = Adapter->Next;
00110 }
00111
00112 free(AdapterInfo);
00113 return count;
00114 }
00115
00116 hdhomerun_sock_t hdhomerun_sock_create_udp(void)
00117 {
00118
00119 hdhomerun_sock_t sock = (hdhomerun_sock_t)socket(AF_INET, SOCK_DGRAM, 0);
00120 if (sock == -1) {
00121 return HDHOMERUN_SOCK_INVALID;
00122 }
00123
00124
00125 unsigned long mode = 1;
00126 if (ioctlsocket(sock, FIONBIO, &mode) != 0) {
00127 closesocket(sock);
00128 return HDHOMERUN_SOCK_INVALID;
00129 }
00130
00131
00132 int sock_opt = 1;
00133 setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&sock_opt, sizeof(sock_opt));
00134
00135
00136 return sock;
00137 }
00138
00139 hdhomerun_sock_t hdhomerun_sock_create_tcp(void)
00140 {
00141
00142 hdhomerun_sock_t sock = (hdhomerun_sock_t)socket(AF_INET, SOCK_STREAM, 0);
00143 if (sock == -1) {
00144 return HDHOMERUN_SOCK_INVALID;
00145 }
00146
00147
00148 unsigned long mode = 1;
00149 if (ioctlsocket(sock, FIONBIO, &mode) != 0) {
00150 closesocket(sock);
00151 return HDHOMERUN_SOCK_INVALID;
00152 }
00153
00154
00155 return sock;
00156 }
00157
00158 void hdhomerun_sock_destroy(hdhomerun_sock_t sock)
00159 {
00160 closesocket(sock);
00161 }
00162
00163 int hdhomerun_sock_getlasterror(void)
00164 {
00165 return WSAGetLastError();
00166 }
00167
00168 uint32_t hdhomerun_sock_getsockname_addr(hdhomerun_sock_t sock)
00169 {
00170 struct sockaddr_in sock_addr;
00171 int sockaddr_size = sizeof(sock_addr);
00172
00173 if (getsockname(sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
00174 return 0;
00175 }
00176
00177 return ntohl(sock_addr.sin_addr.s_addr);
00178 }
00179
00180 uint16_t hdhomerun_sock_getsockname_port(hdhomerun_sock_t sock)
00181 {
00182 struct sockaddr_in sock_addr;
00183 int sockaddr_size = sizeof(sock_addr);
00184
00185 if (getsockname(sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
00186 return 0;
00187 }
00188
00189 return ntohs(sock_addr.sin_port);
00190 }
00191
00192 uint32_t hdhomerun_sock_getpeername_addr(hdhomerun_sock_t sock)
00193 {
00194 struct sockaddr_in sock_addr;
00195 int sockaddr_size = sizeof(sock_addr);
00196
00197 if (getpeername(sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
00198 return 0;
00199 }
00200
00201 return ntohl(sock_addr.sin_addr.s_addr);
00202 }
00203
00204 uint32_t hdhomerun_sock_getaddrinfo_addr(hdhomerun_sock_t sock, const char *name)
00205 {
00206 struct addrinfo hints;
00207 memset(&hints, 0, sizeof(hints));
00208 hints.ai_family = AF_INET;
00209 hints.ai_socktype = SOCK_STREAM;
00210 hints.ai_protocol = IPPROTO_TCP;
00211
00212 struct addrinfo *sock_info;
00213 if (getaddrinfo(name, "", &hints, &sock_info) != 0) {
00214 return 0;
00215 }
00216
00217 struct sockaddr_in *sock_addr = (struct sockaddr_in *)sock_info->ai_addr;
00218 uint32_t addr = ntohl(sock_addr->sin_addr.s_addr);
00219
00220 freeaddrinfo(sock_info);
00221 return addr;
00222 }
00223
00224 bool_t hdhomerun_sock_bind(hdhomerun_sock_t sock, uint32_t local_addr, uint16_t local_port, bool_t allow_reuse)
00225 {
00226 int sock_opt = allow_reuse;
00227 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&sock_opt, sizeof(sock_opt));
00228
00229 struct sockaddr_in sock_addr;
00230 memset(&sock_addr, 0, sizeof(sock_addr));
00231 sock_addr.sin_family = AF_INET;
00232 sock_addr.sin_addr.s_addr = htonl(local_addr);
00233 sock_addr.sin_port = htons(local_port);
00234
00235 if (bind(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) {
00236 return FALSE;
00237 }
00238
00239 return TRUE;
00240 }
00241
00242 bool_t hdhomerun_sock_connect(hdhomerun_sock_t sock, uint32_t remote_addr, uint16_t remote_port, uint64_t timeout)
00243 {
00244 WSAEVENT wsa_event = WSACreateEvent();
00245 if (wsa_event == WSA_INVALID_EVENT) {
00246 return FALSE;
00247 }
00248
00249 if (WSAEventSelect(sock, wsa_event, FD_CONNECT) == SOCKET_ERROR) {
00250 WSACloseEvent(wsa_event);
00251 return FALSE;
00252 }
00253
00254
00255 struct sockaddr_in sock_addr;
00256 memset(&sock_addr, 0, sizeof(sock_addr));
00257 sock_addr.sin_family = AF_INET;
00258 sock_addr.sin_addr.s_addr = htonl(remote_addr);
00259 sock_addr.sin_port = htons(remote_port);
00260
00261 if (connect(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) {
00262 if (WSAGetLastError() != WSAEWOULDBLOCK) {
00263 WSACloseEvent(wsa_event);
00264 return FALSE;
00265 }
00266 }
00267
00268
00269 DWORD ret = WaitForSingleObjectEx(wsa_event, (DWORD)timeout, FALSE);
00270 WSACloseEvent(wsa_event);
00271
00272 if (ret != WAIT_OBJECT_0) {
00273 return FALSE;
00274 }
00275
00276
00277 int sockaddr_size = sizeof(sock_addr);
00278 if (getpeername(sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
00279 return FALSE;
00280 }
00281
00282 return TRUE;
00283 }
00284
00285 static bool_t hdhomerun_sock_wait_for_event(hdhomerun_sock_t sock, long event_type, uint64_t stop_time)
00286 {
00287 uint64_t current_time = getcurrenttime();
00288 if (current_time >= stop_time) {
00289 return FALSE;
00290 }
00291
00292 WSAEVENT wsa_event = WSACreateEvent();
00293 if (wsa_event == WSA_INVALID_EVENT) {
00294 return FALSE;
00295 }
00296
00297 if (WSAEventSelect(sock, wsa_event, event_type) == SOCKET_ERROR) {
00298 WSACloseEvent(wsa_event);
00299 return FALSE;
00300 }
00301
00302 DWORD ret = WaitForSingleObjectEx(wsa_event, (DWORD)(stop_time - current_time), FALSE);
00303 WSACloseEvent(wsa_event);
00304
00305 if (ret != WAIT_OBJECT_0) {
00306 return FALSE;
00307 }
00308
00309 return TRUE;
00310 }
00311
00312 bool_t hdhomerun_sock_send(hdhomerun_sock_t sock, const void *data, size_t length, uint64_t timeout)
00313 {
00314 uint64_t stop_time = getcurrenttime() + timeout;
00315 const uint8_t *ptr = (uint8_t *)data;
00316
00317 while (1) {
00318 int ret = send(sock, (char *)ptr, (int)length, 0);
00319 if (ret >= (int)length) {
00320 return TRUE;
00321 }
00322
00323 if (ret > 0) {
00324 ptr += ret;
00325 length -= ret;
00326 }
00327
00328 if (WSAGetLastError() != WSAEWOULDBLOCK) {
00329 return FALSE;
00330 }
00331
00332 if (!hdhomerun_sock_wait_for_event(sock, FD_WRITE | FD_CLOSE, stop_time)) {
00333 return FALSE;
00334 }
00335 }
00336 }
00337
00338 bool_t hdhomerun_sock_sendto(hdhomerun_sock_t sock, uint32_t remote_addr, uint16_t remote_port, const void *data, size_t length, uint64_t timeout)
00339 {
00340 uint64_t stop_time = getcurrenttime() + timeout;
00341 const uint8_t *ptr = (uint8_t *)data;
00342
00343 while (1) {
00344 struct sockaddr_in sock_addr;
00345 memset(&sock_addr, 0, sizeof(sock_addr));
00346 sock_addr.sin_family = AF_INET;
00347 sock_addr.sin_addr.s_addr = htonl(remote_addr);
00348 sock_addr.sin_port = htons(remote_port);
00349
00350 int ret = sendto(sock, (char *)ptr, (int)length, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr));
00351 if (ret >= (int)length) {
00352 return TRUE;
00353 }
00354
00355 if (ret > 0) {
00356 ptr += ret;
00357 length -= ret;
00358 }
00359
00360 if (WSAGetLastError() != WSAEWOULDBLOCK) {
00361 return FALSE;
00362 }
00363
00364 if (!hdhomerun_sock_wait_for_event(sock, FD_WRITE | FD_CLOSE, stop_time)) {
00365 return FALSE;
00366 }
00367 }
00368 }
00369
00370 bool_t hdhomerun_sock_recv(hdhomerun_sock_t sock, void *data, size_t *length, uint64_t timeout)
00371 {
00372 uint64_t stop_time = getcurrenttime() + timeout;
00373
00374 while (1) {
00375 int ret = recv(sock, (char *)data, (int)(*length), 0);
00376 if (ret > 0) {
00377 *length = ret;
00378 return TRUE;
00379 }
00380
00381 if (WSAGetLastError() != WSAEWOULDBLOCK) {
00382 return FALSE;
00383 }
00384
00385 if (!hdhomerun_sock_wait_for_event(sock, FD_READ | FD_CLOSE, stop_time)) {
00386 return FALSE;
00387 }
00388 }
00389 }
00390
00391 bool_t hdhomerun_sock_recvfrom(hdhomerun_sock_t sock, uint32_t *remote_addr, uint16_t *remote_port, void *data, size_t *length, uint64_t timeout)
00392 {
00393 uint64_t stop_time = getcurrenttime() + timeout;
00394
00395 while (1) {
00396 struct sockaddr_in sock_addr;
00397 memset(&sock_addr, 0, sizeof(sock_addr));
00398 int sockaddr_size = sizeof(sock_addr);
00399
00400 int ret = recvfrom(sock, (char *)data, (int)(*length), 0, (struct sockaddr *)&sock_addr, &sockaddr_size);
00401 if (ret > 0) {
00402 *remote_addr = ntohl(sock_addr.sin_addr.s_addr);
00403 *remote_port = ntohs(sock_addr.sin_port);
00404 *length = ret;
00405 return TRUE;
00406 }
00407
00408 if (WSAGetLastError() != WSAEWOULDBLOCK) {
00409 return FALSE;
00410 }
00411
00412 if (!hdhomerun_sock_wait_for_event(sock, FD_READ | FD_CLOSE, stop_time)) {
00413 return FALSE;
00414 }
00415 }
00416 }