cmake: supernova - missing include_directories() for Jack
[supercollider.git] / lang / LangPrimSource / SC_ComPort.cpp
blob2e9fbd15b5560923720e8bca6433cf3ceea973d1
1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program 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.
11 This program 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.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "SC_BoundsMacros.h"
22 #include "SC_ComPort.h"
23 #include "SC_Endian.h"
24 //#include "SC_Lock.h"
25 #include <ctype.h>
26 #include <stdexcept>
27 #include <stdarg.h>
28 #include "SCBase.h"
29 #include <fcntl.h>
31 #ifndef SC_WIN32
32 # include <unistd.h>
33 #else
34 #include "SC_Win32Utils.h"
35 #endif
37 #ifdef SC_LINUX
38 # include <errno.h>
39 #endif
41 #ifdef __FreeBSD__
42 # include <errno.h>
43 #endif
45 #if defined(SC_DARWIN) || defined(SC_IPHONE)
46 #include <errno.h>
47 #endif
49 // sk: determine means of blocking SIGPIPE for send(2) (implementation
50 // dependent)
52 #define HAVE_SO_NOSIGPIPE 0
53 #define HAVE_MSG_NOSIGNAL 0
55 #if defined(SO_NOSIGPIPE)
56 # undef HAVE_SO_NOSIGPIPE
57 # define HAVE_SO_NOSIGPIPE 1
58 #elif defined(MSG_NOSIGNAL)
59 # undef HAVE_MSG_NOSIGNAL
60 # define HAVE_MSG_NOSIGNAL 1
61 #endif
63 int recvall(int socket, void *msg, size_t len);
64 int recvallfrom(int socket, void *msg, size_t len, struct sockaddr *fromaddr, int addrlen);
65 int sendallto(int socket, const void *msg, size_t len, struct sockaddr *toaddr, int addrlen);
66 int sendall(int socket, const void *msg, size_t len);
68 void ProcessOSCPacket(OSC_Packet *inPacket, int inPortNum);
70 void dumpOSCmsg(int inSize, char* inData)
72 int size;
73 const char *data;
75 if (inData[0]) {
76 char *addr = inData;
77 data = OSCstrskip(inData);
78 size = inSize - (data - inData);
79 printf("[ \"%s\",", addr);
81 else
83 printf("[ %d,", OSCint(inData));
84 data = inData + 4;
85 size = inSize - 4;
88 sc_msg_iter msg(size, data);
90 while (msg.remain())
92 char c = msg.nextTag('i');
93 switch(c)
95 case 'i' :
96 printf(" %d", msg.geti());
97 break;
98 case 'f' :
99 printf(" %g", msg.getf());
100 break;
101 case 'd' :
102 printf(" %g", msg.getd());
103 break;
104 case 's' :
105 printf(" \"%s\"", msg.gets());
106 break;
107 case 'b' :
108 printf(" DATA[%zu]", msg.getbsize());
109 msg.skipb();
110 break;
111 default :
112 printf(" !unknown tag '%c' 0x%02x !", isprint(c)?c:'?', (unsigned char)c & 255);
113 goto leave;
115 if (msg.remain()) printf(",");
117 leave:
118 printf(" ]");
121 void hexdump(int size, char* data)
123 char ascii[20];
124 int padsize = (size + 15) & -16;
125 printf("size %d\n", size);
126 for (int i=0; i<padsize; ++i)
128 if ((i&15)==0)
130 printf("%4d ", i);
132 if (i >= size)
134 printf(" ");
135 ascii[i&15] = 0;
137 else
139 printf("%02x ", (unsigned char)data[i] & 255);
141 if (isprint(data[i])) ascii[i&15] = data[i];
142 else ascii[i&15] = '.';
144 if ((i&15)==15)
146 ascii[16] = 0;
147 printf(" |%s|\n", ascii);
149 else if ((i&3)==3)
151 printf(" ");
154 printf("\n");
157 void dumpOSC(int mode, int size, char* inData)
159 if (mode & 1)
161 if (strcmp(inData, "#bundle") == 0)
163 char* data = inData + 8;
164 printf("[ \"#bundle\", %lld, ", OSCtime(data));
165 data += 8;
166 char* dataEnd = inData + size;
167 while (data < dataEnd) {
168 int32 msgSize = OSCint(data);
169 data += sizeof(int32);
170 printf("\n ");
171 dumpOSCmsg(msgSize, data);
172 data += msgSize;
173 if (data < dataEnd) printf(",");
175 printf("\n]\n");
177 else
179 dumpOSCmsg(size, inData);
180 printf("\n");
184 if (mode & 2) hexdump(size, inData);
187 //////////////////////////////////////////////////////////////////////////////////////////////////////////
189 SC_CmdPort::SC_CmdPort()
193 SC_CmdPort::~SC_CmdPort()
197 //////////////////////////////////////////////////////////////////////////////////////////////////////////
199 SC_ComPort::SC_ComPort(int inPortNum)
200 : mPortNum(inPortNum), mSocket(-1)
204 SC_ComPort::~SC_ComPort()
206 #ifdef SC_WIN32
207 if (mSocket != -1) closesocket(mSocket);
208 #else
209 if (mSocket != -1) close(mSocket);
210 #endif
213 static void* com_thread_func(void* arg)
215 SC_CmdPort *thread = (SC_CmdPort*)arg;
216 void* result = thread->Run();
217 return result;
220 void SC_CmdPort::Start()
222 pthread_create (&mThread, NULL, com_thread_func, (void*)this);
225 //////////////////////////////////////////////////////////////////////////////////////////////////////////
227 SC_UdpInPort::SC_UdpInPort(int inPortNum)
228 : SC_ComPort(inPortNum)
230 if ((mSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
231 throw std::runtime_error("failed to create udp socket\n");
235 int bufsize = 65536;
236 #ifdef SC_WIN32
237 setsockopt(mSocket, SOL_SOCKET, SO_SNDBUF, (char*)&bufsize, sizeof(bufsize));
238 #else
239 setsockopt(mSocket, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
240 #endif
243 bzero((char *)&mBindSockAddr, sizeof(mBindSockAddr));
244 mBindSockAddr.sin_family = AF_INET;
245 mBindSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
247 bool bound = false;
248 for (int i=0; i<10 && !bound; ++i) {
249 mPortNum = mPortNum+i;
250 mBindSockAddr.sin_port = htons(mPortNum);
251 if (bind(mSocket, (struct sockaddr *)&mBindSockAddr, sizeof(mBindSockAddr)) >= 0) {
252 bound = true;
255 if (!bound) throw std::runtime_error("unable to bind udp socket\n");
256 Start();
259 SC_UdpInPort::~SC_UdpInPort()
261 #ifdef SC_WIN32
262 if (mSocket != -1) closesocket(mSocket);
263 #else
264 if (mSocket != -1) close(mSocket);
265 #endif
268 //////////////////////////////////////////////////////////////////////////////////////////////////////////
270 SC_UdpCustomInPort::SC_UdpCustomInPort(int inPortNum)
271 : SC_ComPort(inPortNum)
273 if ((mSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
274 throw std::runtime_error("failed to create udp socket\n");
278 int bufsize = 65536;
279 #ifdef SC_WIN32
280 setsockopt(mSocket, SOL_SOCKET, SO_SNDBUF, (char*)&bufsize, sizeof(bufsize));
281 #else
282 setsockopt(mSocket, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
283 #endif
286 bzero((char *)&mBindSockAddr, sizeof(mBindSockAddr));
287 mBindSockAddr.sin_family = AF_INET;
288 mBindSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
290 bool bound = false;
291 mBindSockAddr.sin_port = htons(mPortNum);
292 if (bind(mSocket, (struct sockaddr *)&mBindSockAddr, sizeof(mBindSockAddr)) >= 0) {
293 bound = true;
295 if (!bound) throw std::runtime_error("unable to bind udp socket\n");
296 Start();
299 SC_UdpCustomInPort::~SC_UdpCustomInPort()
301 mRunning.store(false);
302 pthread_join(mThread, NULL);
303 #ifdef SC_WIN32
304 if (mSocket != -1) closesocket(mSocket);
305 #else
306 if (mSocket != -1) close(mSocket);
307 #endif
311 //////////////////////////////////////////////////////////////////////////////////////////////////////////
313 void DumpReplyAddress(ReplyAddress *inReplyAddress)
315 printf("mSockAddrLen %d\n", inReplyAddress->mSockAddrLen);
316 printf("mSocket %d\n", inReplyAddress->mSocket);
317 #ifdef SC_DARWIN
318 printf("mSockAddr.sin_len %d\n", inReplyAddress->mSockAddr.sin_len);
319 #endif
320 printf("mSockAddr.sin_family %d\n", inReplyAddress->mSockAddr.sin_family);
321 printf("mSockAddr.sin_port %d\n", inReplyAddress->mSockAddr.sin_port);
322 printf("mSockAddr.sin_addr.s_addr %d\n", inReplyAddress->mSockAddr.sin_addr.s_addr);
323 printf("mReplyFunc %p\n", inReplyAddress->mReplyFunc);
327 int32 Hash(ReplyAddress *inReplyAddress)
329 int32 hash;
330 int32 *word = (int32*)&inReplyAddress->mSockAddr;
331 hash = Hash(inReplyAddress->mSockAddr.sin_addr.s_addr);
333 hash += inReplyAddress->mSockAddr.sin_len << 24
334 | inReplyAddress->mSockAddr.sin_family << 16
335 | inReplyAddress->mSockAddr.sin_port;
337 hash = Hash(hash);
338 return hash;
342 void udp_reply_func(struct ReplyAddress *addr, char* msg, int size);
343 void udp_reply_func(struct ReplyAddress *addr, char* msg, int size)
345 printf("->udp_reply_func\n");
346 int total = sendallto(addr->mSocket, msg, size, (sockaddr*)&addr->mSockAddr, addr->mSockAddrLen);
347 printf("<-udp_reply_func %d of %d\n", total, size);
348 if (total < size) DumpReplyAddress(addr);
351 ReplyFunc SC_UdpInPort::GetReplyFunc()
353 return udp_reply_func;
356 void* SC_UdpInPort::Run()
358 OSC_Packet *packet = 0;
360 //printf("SC_UdpInPort::Run\n"); fflush(stdout);
362 while (true) {
363 if (!packet) {
364 packet = (OSC_Packet*)malloc(sizeof(OSC_Packet));
366 packet->mReplyAddr.mSockAddrLen = sizeof(sockaddr_in);
367 int size = recvfrom(mSocket, buf, kTextBufSize , 0,
368 (struct sockaddr *) &packet->mReplyAddr.mSockAddr, (socklen_t*)&packet->mReplyAddr.mSockAddrLen);
370 if (size > 0) {
371 //dumpOSC(3, size, buf);
372 //fflush(stdout);
374 char *data = (char*)malloc(size);
375 packet->mReplyAddr.mReplyFunc = udp_reply_func;
376 packet->mSize = size;
377 packet->mData = data;
378 packet->mReplyAddr.mSocket = mSocket;
379 memcpy(data, buf, size);
380 ProcessOSCPacket(packet, mPortNum);
381 packet = 0;
384 return 0;
387 ReplyFunc SC_UdpCustomInPort::GetReplyFunc()
389 return udp_reply_func;
392 void* SC_UdpCustomInPort::Run()
394 OSC_Packet *packet = 0;
396 const int fd = mSocket;
397 const int max_fd = fd+1;
399 mRunning.store(true);
400 while (mRunning.load(boost::memory_order_consume)) {
401 fd_set rfds;
403 FD_ZERO( &rfds);
404 FD_SET(fd, &rfds);
406 struct timeval timeout;
407 timeout.tv_sec = 0;
408 timeout.tv_usec = 500000;
410 int n = select(max_fd, &rfds, 0, 0, &timeout);
411 if ((n > 0) && FD_ISSET(fd, &rfds)) {
412 if (!packet) {
413 packet = (OSC_Packet*)malloc(sizeof(OSC_Packet));
415 packet->mReplyAddr.mSockAddrLen = sizeof(sockaddr_in);
416 int size = recvfrom(mSocket, buf, kTextBufSize , 0,
417 (struct sockaddr *) &packet->mReplyAddr.mSockAddr, (socklen_t*)&packet->mReplyAddr.mSockAddrLen);
419 if (size > 0 && mRunning.load(boost::memory_order_consume)) {
420 //dumpOSC(3, size, buf);
421 //fflush(stdout);
423 char *data = (char*)malloc(size);
424 packet->mReplyAddr.mReplyFunc = udp_reply_func;
425 packet->mSize = size;
426 packet->mData = data;
427 packet->mReplyAddr.mSocket = mSocket;
428 memcpy(data, buf, size);
429 ProcessOSCPacket(packet, mPortNum);
430 packet = 0;
434 FreeOSCPacket(packet); // just in case
435 return 0;
438 //////////////////////////////////////////////////////////////////////////////////////////////////////////
440 SC_TcpInPort::SC_TcpInPort(int inPortNum, int inMaxConnections, int inBacklog)
441 : SC_ComPort(inPortNum), mConnectionAvailable(inMaxConnections),
442 mBacklog(inBacklog)
445 if((mSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
446 throw std::runtime_error("failed to create tcp socket\n");
448 //setsockopt(mSocket, SOL_SOCKET, TCP_NODELAY);
450 bzero((char *)&mBindSockAddr, sizeof(mBindSockAddr));
451 mBindSockAddr.sin_family = AF_INET;
452 mBindSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
453 mBindSockAddr.sin_port = htons(mPortNum);
455 if(bind(mSocket, (struct sockaddr *)&mBindSockAddr, sizeof(mBindSockAddr)) < 0)
457 throw std::runtime_error("unable to bind tcp socket\n");
459 if(listen(mSocket, mBacklog) < 0)
461 throw std::runtime_error("unable to listen tcp socket\n");
464 Start();
467 void* SC_TcpInPort::Run()
469 while (true)
471 mConnectionAvailable.Acquire();
472 struct sockaddr_in address; /* Internet socket address stuct */
473 int addressSize=sizeof(struct sockaddr_in);
474 int socket = accept(mSocket,(struct sockaddr*)&address,(socklen_t*)&addressSize);
475 if (socket < 0) {
476 mConnectionAvailable.Release();
477 } else {
478 new SC_TcpConnectionPort(this, socket);
481 return 0;
484 void SC_TcpInPort::ConnectionTerminated()
486 mConnectionAvailable.Release();
489 void null_reply_func(struct ReplyAddress *addr, char* msg, int size);
490 void null_reply_func(struct ReplyAddress *addr, char* msg, int size)
494 ReplyFunc SC_TcpInPort::GetReplyFunc()
496 return null_reply_func;
499 //////////////////////////////////////////////////////////////////////////////////////////////////////////
501 SC_TcpConnectionPort::SC_TcpConnectionPort(SC_TcpInPort *inParent, int inSocket)
502 : SC_ComPort(0), mParent(inParent)
504 mSocket = inSocket;
505 Start();
508 SC_TcpConnectionPort::~SC_TcpConnectionPort()
510 #ifdef SC_WIN32
511 closesocket(mSocket);
512 #else
513 close(mSocket);
514 #endif
515 mParent->ConnectionTerminated();
518 void tcp_reply_func(struct ReplyAddress *addr, char* msg, int size);
519 void tcp_reply_func(struct ReplyAddress *addr, char* msg, int size)
521 sendall(addr->mSocket, msg, size);
524 ReplyFunc SC_TcpConnectionPort::GetReplyFunc()
526 return tcp_reply_func;
529 extern const char* gPassword;
531 void* SC_TcpConnectionPort::Run()
533 OSC_Packet *packet = 0;
534 // wait for login message
535 int32 size;
536 int32 msglen;
538 while (true) {
539 if (!packet) {
540 packet = (OSC_Packet*)malloc(sizeof(OSC_Packet));
542 size = recvall(mSocket, &msglen, sizeof(int32));
543 if (size < 0) goto leave;
545 // sk: msglen is in network byte order
546 msglen = ntohl(msglen);
548 char *data = (char*)malloc(msglen);
549 size = recvall(mSocket, data, msglen);
550 if (size < msglen) goto leave;
552 packet->mReplyAddr.mReplyFunc = tcp_reply_func;
553 packet->mSize = msglen;
554 packet->mData = data;
555 packet->mReplyAddr.mSocket = mSocket;
556 ProcessOSCPacket(packet, mPortNum);
557 packet = 0;
559 leave:
560 delete this; // ohh this could cause a crash if a reply tries to access it..
561 return 0;
564 //////////////////////////////////////////////////////////////////////////////////////////////////////////
566 #ifndef SC_WIN32
567 # include <sys/select.h>
568 #endif
569 //SC_WIN32
571 SC_TcpClientPort::SC_TcpClientPort(int inSocket, ClientNotifyFunc notifyFunc, void *clientData)
572 : SC_ComPort(0),
573 mClientNotifyFunc(notifyFunc),
574 mClientData(clientData)
576 mSocket = inSocket;
577 socklen_t sockAddrLen = sizeof(mReplySockAddr);
579 if (getpeername(mSocket, (struct sockaddr*)&mReplySockAddr, &sockAddrLen) == -1) {
580 memset(&mReplySockAddr, 0, sizeof(mReplySockAddr));
581 mReplySockAddr.sin_family = AF_INET;
582 mReplySockAddr.sin_addr.s_addr = htonl(INADDR_NONE);
583 mReplySockAddr.sin_port = htons(0);
586 #if HAVE_SO_NOSIGPIPE
587 int sockopt = 1;
588 setsockopt(mSocket, SOL_SOCKET, SO_NOSIGPIPE, &sockopt, sizeof(sockopt));
589 #endif // HAVE_SO_NOSIGPIPE
591 if (pipe(mCmdFifo) == -1) {
592 mCmdFifo[0] = mCmdFifo[1] = -1;
595 Start();
598 SC_TcpClientPort::~SC_TcpClientPort()
600 #ifdef SC_WIN32
601 closesocket(mCmdFifo[0]);
602 closesocket(mCmdFifo[1]);
603 closesocket(mSocket);
604 #else
605 close(mCmdFifo[0]);
606 close(mCmdFifo[1]);
607 close(mSocket);
608 #endif
611 void* SC_TcpClientPort::Run()
613 OSC_Packet *packet = 0;
614 int32 size;
615 int32 msglen;
617 int cmdfd = mCmdFifo[0];
618 int sockfd = mSocket;
619 int nfds = sc_max(cmdfd, sockfd) + 1;
621 bool cmdClose = false;
623 pthread_detach(mThread);
625 while (true) {
626 fd_set rfds;
627 FD_ZERO(&rfds);
628 FD_SET(cmdfd, &rfds);
629 FD_SET(sockfd, &rfds);
631 if ((select(nfds, &rfds, 0, 0, 0) == -1) || (cmdClose = FD_ISSET(cmdfd, &rfds)))
632 goto leave;
634 if (!FD_ISSET(sockfd, &rfds))
635 continue;
637 packet = (OSC_Packet*)malloc(sizeof(OSC_Packet));
638 if (!packet) goto leave;
640 packet->mData = 0;
642 size = recvall(sockfd, &msglen, sizeof(int32));
643 if (size < (int32)sizeof(int32)) goto leave;
645 // msglen is in network byte order
646 msglen = ntohl(msglen);
648 packet->mData = (char*)malloc(msglen);
649 if (!packet->mData) goto leave;
651 size = recvall(sockfd, packet->mData, msglen);
652 if (size < msglen) goto leave;
654 memcpy(&packet->mReplyAddr.mSockAddr, &mReplySockAddr, sizeof(mReplySockAddr));
655 packet->mReplyAddr.mSockAddrLen = sizeof(mReplySockAddr);
656 packet->mReplyAddr.mSocket = sockfd;
657 packet->mReplyAddr.mReplyFunc = tcp_reply_func;
658 packet->mSize = msglen;
659 ProcessOSCPacket(packet, mPortNum);
661 packet = 0;
664 leave:
665 if (packet) {
666 free(packet->mData);
667 free(packet);
669 // Only call notify function when not closed explicitly
670 if (!cmdClose && mClientNotifyFunc) {
671 (*mClientNotifyFunc)(mClientData);
673 delete this;
674 return 0;
677 void SC_TcpClientPort::Close()
679 char cmd = 0;
680 #ifdef SC_WIN32
681 win32_pipewrite(mCmdFifo[1], &cmd, sizeof(cmd));
682 #else
683 size_t written = write(mCmdFifo[1], &cmd, sizeof(cmd));
684 if (written != sizeof(cmd))
685 post("warning: invalid write in SC_TcpClientPort::Close");
686 #endif
689 ReplyFunc SC_TcpClientPort::GetReplyFunc()
691 return tcp_reply_func;
694 //////////////////////////////////////////////////////////////////////////////////////////////////////////
696 int recvall(int socket, void *msg, size_t len)
698 size_t total = 0;
699 while (total < len)
701 #ifdef SC_WIN32
702 int numbytes = recv(socket, reinterpret_cast<char*>(msg), len - total, 0);
703 #else
704 int numbytes = recv(socket, msg, len - total, 0);
705 #endif
706 if (numbytes <= 0) return total;
707 total += numbytes;
708 msg = (void*)((char*)msg + numbytes);
710 return total;
713 int recvallfrom(int socket, void *msg, size_t len, struct sockaddr *fromaddr, int addrlen)
715 size_t total = 0;
716 while (total < len)
718 socklen_t addrlen2 = addrlen;
719 #ifdef SC_WIN32
720 int numbytes = recvfrom(socket, reinterpret_cast<char*>(msg), len - total, 0, fromaddr, &addrlen2);
721 #else
722 int numbytes = recvfrom(socket, msg, len - total, 0, fromaddr, &addrlen2);
723 #endif
724 if (numbytes < 0) return total;
725 total += numbytes;
726 msg = (void*)((char*)msg + numbytes);
728 return total;
731 int sendallto(int socket, const void *msg, size_t len, struct sockaddr *toaddr, int addrlen)
733 size_t total = 0;
734 while (total < len)
736 #ifdef SC_WIN32
737 int numbytes = sendto(socket, reinterpret_cast<const char*>(msg), len - total, 0, toaddr, addrlen);
738 #else
739 int numbytes = sendto(socket, msg, len - total, 0, toaddr, addrlen);
740 #endif
741 //printf("numbytes %d total %d len %d\n", numbytes, total, len);
742 if (numbytes < 0) {
743 printf("******* errno %d %s\n", errno, strerror(errno));
744 return total;
746 total += numbytes;
747 msg = (void*)((char*)msg + numbytes);
749 return total;
752 int sendall(int socket, const void *msg, size_t len)
754 size_t total = 0;
755 while (total < len)
757 #if HAVE_MSG_NOSIGNAL
758 int flags = MSG_NOSIGNAL;
759 #else
760 int flags = 0;
761 #endif // HAVE_MSG_NOSIGNAL
762 #ifdef SC_WIN32
763 int numbytes = send(socket, reinterpret_cast<const char*>(msg), len - total, flags);
764 #else
765 int numbytes = send(socket, msg, len - total, flags);
766 #endif
767 if (numbytes < 0) return total;
768 total += numbytes;
769 msg = (void*)((char*)msg + numbytes);
771 return total;
774 //////////////////////////////////////////////////////////////////////////////////////////////////////////