forked from PlusToolkit/ndicapi
-
Notifications
You must be signed in to change notification settings - Fork 3
/
ndicapi_socket_unix.cxx
165 lines (143 loc) · 4.57 KB
/
ndicapi_socket_unix.cxx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/*=Plus=header=begin======================================================
Program: Plus
Copyright (c) Laboratory for Percutaneous Surgery. All rights reserved.
See License.md for details.
=========================================================Plus=header=end*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/time.h>
//----------------------------------------------------------------------------
ndicapiExport bool ndiSocketOpen(const char* hostname, int port, NDISocketHandle& outSocket)
{
NDISocketHandle sock = socket(AF_INET, SOCK_STREAM, 0);
// Eliminate windows 0.2 second delay sending (buffering) data.
int on = 1;
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on)))
{
return false;
}
struct hostent* hp;
hp = gethostbyname(hostname);
if (!hp)
{
unsigned long addr = inet_addr(hostname);
hp = gethostbyaddr((char*)&addr, sizeof(addr), AF_INET);
}
if (!hp)
{
return false;
}
struct sockaddr_in name;
name.sin_family = AF_INET;
memcpy(&name.sin_addr, hp->h_addr, hp->h_length);
name.sin_port = htons(port);
int r = connect(sock, reinterpret_cast<sockaddr*>(&name), sizeof(name));
if (r < 0)
{
shutdown(sock, 2);
close(sock);
return false;
}
outSocket = sock;
return true;
}
//----------------------------------------------------------------------------
ndicapiExport void ndiSocketClose(NDISocketHandle socket)
{
shutdown(socket, 2);
close(socket);
}
//----------------------------------------------------------------------------
ndicapiExport bool ndiSocketFlush(NDISocketHandle socket, int flushtype)
{
return true;
}
//----------------------------------------------------------------------------
ndicapiExport bool ndiSocketTimeout(NDISocketHandle socket, int timeoutMs)
{
if (timeoutMs > 0)
{
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char*) & (timeoutMs), sizeof(timeoutMs));
return true;
}
return false;
}
//----------------------------------------------------------------------------
ndicapiExport int ndiSocketWrite(NDISocketHandle socket, const char* data, int length)
{
if (length == 0)
{
// nothing to send.
return 0;
}
const char* buffer = reinterpret_cast<const char*>(data);
int total = 0;
do
{
int flags;
// On unix boxes if the client disconnects and the server attempts
// to send data through the socket then the application crashes
// due to SIGPIPE signal. Disable the signal to prevent crash.
#if defined(MSG_NOSIGNAL) // For Linux > 2.2
flags = MSG_NOSIGNAL;
#else
flags = 0;
#endif
int n = send(socket, buffer + total, length - total, flags);
if (n < 0)
{
return -1;
}
total += n;
}
while (total < length);
return total;
}
//----------------------------------------------------------------------------
ndicapiExport int ndiSocketRead(NDISocketHandle socket, char* reply, int numberOfBytesToRead, bool isBinary, int* outErrorCode)
{
int totalNumberOfBytesRead = 0;
int totalNumberOfBytesToRead = numberOfBytesToRead;
int numberOfBytesRead;
bool binarySizeCalculated = false;
do
{
numberOfBytesRead = recv(socket, reply + totalNumberOfBytesRead, numberOfBytesToRead, 0);
if (numberOfBytesRead < 1)
{
return -1;
}
totalNumberOfBytesRead += numberOfBytesRead;
if ((!isBinary && reply[totalNumberOfBytesRead - 1] == '\r') /* done when carriage return received (ASCII) or when ERROR... received (binary)*/
|| (isBinary && strncmp(reply, "ERROR", 5) == 0 && reply[totalNumberOfBytesRead - 1] == '\r'))
{
break;
}
if (isBinary && !binarySizeCalculated && reply[0] == (char)0xc4 && reply[1] == (char)0xa5)
{
// recalculate n based on the reply length (reported from ndi device) and the amount of data received so far
unsigned short size = ((unsigned char)reply[2] | (unsigned char)reply[3] << 8) + 8; // 8 bytes -> 2 for Start Sequence (a5c4), 2 for reply length, 2 for header CRC, 2 for CRC16
totalNumberOfBytesToRead = size;
}
}
while (totalNumberOfBytesRead != totalNumberOfBytesToRead);
return totalNumberOfBytesRead;
}
//----------------------------------------------------------------------------
ndicapiExport bool ndiSocketSleep(NDISocketHandle socket, int milliseconds)
{
#if _POSIX_C_SOURCE >= 199309L
struct timespec ts;
ts.tv_sec = milliseconds / 1000;
ts.tv_nsec = (milliseconds % 1000) * 1000000;
nanosleep(&ts, NULL);
#else
usleep(milliseconds * 1000);
#endif
return true;
}