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"
33 #include "SC_Win32Utils.h"
44 #if defined(SC_DARWIN) || defined(SC_IPHONE)
48 // sk: determine means of blocking SIGPIPE for send(2) (implementation
51 #define HAVE_SO_NOSIGPIPE 0
52 #define HAVE_MSG_NOSIGNAL 0
54 #if defined(SO_NOSIGPIPE)
55 # undef HAVE_SO_NOSIGPIPE
56 # define HAVE_SO_NOSIGPIPE 1
57 #elif defined(MSG_NOSIGNAL)
58 # undef HAVE_MSG_NOSIGNAL
59 # define HAVE_MSG_NOSIGNAL 1
62 int recvall(int socket
, void *msg
, size_t len
);
63 int recvallfrom(int socket
, void *msg
, size_t len
, struct sockaddr
*fromaddr
, int addrlen
);
64 int sendallto(int socket
, const void *msg
, size_t len
, struct sockaddr
*toaddr
, int addrlen
);
65 int sendall(int socket
, const void *msg
, size_t len
);
67 void ProcessOSCPacket(OSC_Packet
*inPacket
, int inPortNum
);
69 static void dumpOSCmsg(int inSize
, char* inData
)
76 data
= OSCstrskip(inData
);
77 size
= inSize
- (data
- inData
);
78 printf("[ \"%s\",", addr
);
82 printf("[ %d,", OSCint(inData
));
87 sc_msg_iter
msg(size
, data
);
91 char c
= msg
.nextTag('i');
95 printf(" %d", msg
.geti());
98 printf(" %g", msg
.getf());
101 printf(" %g", msg
.getd());
104 printf(" \"%s\"", msg
.gets());
107 printf(" DATA[%zu]", msg
.getbsize());
111 printf(" !unknown tag '%c' 0x%02x !", isprint(c
)?c
:'?', (unsigned char)c
& 255);
114 if (msg
.remain()) printf(",");
120 static void hexdump(int size
, char* data
)
123 int padsize
= (size
+ 15) & -16;
124 printf("size %d\n", size
);
125 for (int i
=0; i
<padsize
; ++i
)
138 printf("%02x ", (unsigned char)data
[i
] & 255);
140 if (isprint(data
[i
])) ascii
[i
&15] = data
[i
];
141 else ascii
[i
&15] = '.';
146 printf(" |%s|\n", ascii
);
156 void dumpOSC(int mode
, int size
, char* inData
)
160 if (strcmp(inData
, "#bundle") == 0)
162 char* data
= inData
+ 8;
163 printf("[ \"#bundle\", %lld, ", OSCtime(data
));
165 char* dataEnd
= inData
+ size
;
166 while (data
< dataEnd
) {
167 int32 msgSize
= OSCint(data
);
168 data
+= sizeof(int32
);
170 dumpOSCmsg(msgSize
, data
);
172 if (data
< dataEnd
) printf(",");
178 dumpOSCmsg(size
, inData
);
183 if (mode
& 2) hexdump(size
, inData
);
186 //////////////////////////////////////////////////////////////////////////////////////////////////////////
188 SC_CmdPort::SC_CmdPort()
192 SC_CmdPort::~SC_CmdPort()
196 //////////////////////////////////////////////////////////////////////////////////////////////////////////
198 SC_ComPort::SC_ComPort(int inPortNum
)
199 : mPortNum(inPortNum
), mSocket(-1)
203 SC_ComPort::~SC_ComPort()
206 if (mSocket
!= -1) closesocket(mSocket
);
208 if (mSocket
!= -1) close(mSocket
);
212 static void* com_thread_func(void* arg
)
214 SC_CmdPort
*thread
= (SC_CmdPort
*)arg
;
215 void* result
= thread
->Run();
219 void SC_CmdPort::Start()
221 pthread_create (&mThread
, NULL
, com_thread_func
, (void*)this);
224 //////////////////////////////////////////////////////////////////////////////////////////////////////////
226 SC_UdpInPort::SC_UdpInPort(int inPortNum
)
227 : SC_ComPort(inPortNum
)
229 if ((mSocket
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
230 throw std::runtime_error("failed to create udp socket\n");
236 setsockopt(mSocket
, SOL_SOCKET
, SO_SNDBUF
, (char*)&bufsize
, sizeof(bufsize
));
238 setsockopt(mSocket
, SOL_SOCKET
, SO_SNDBUF
, &bufsize
, sizeof(bufsize
));
242 bzero((char *)&mBindSockAddr
, sizeof(mBindSockAddr
));
243 mBindSockAddr
.sin_family
= AF_INET
;
244 mBindSockAddr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
247 for (int i
=0; i
<10 && !bound
; ++i
) {
248 mPortNum
= mPortNum
+i
;
249 mBindSockAddr
.sin_port
= htons(mPortNum
);
250 if (bind(mSocket
, (struct sockaddr
*)&mBindSockAddr
, sizeof(mBindSockAddr
)) >= 0) {
254 if (!bound
) throw std::runtime_error("unable to bind udp socket\n");
258 SC_UdpInPort::~SC_UdpInPort()
261 if (mSocket
!= -1) closesocket(mSocket
);
263 if (mSocket
!= -1) close(mSocket
);
267 //////////////////////////////////////////////////////////////////////////////////////////////////////////
269 SC_UdpCustomInPort::SC_UdpCustomInPort(int inPortNum
)
270 : SC_ComPort(inPortNum
)
272 if ((mSocket
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
273 throw std::runtime_error("failed to create udp socket\n");
279 setsockopt(mSocket
, SOL_SOCKET
, SO_SNDBUF
, (char*)&bufsize
, sizeof(bufsize
));
281 setsockopt(mSocket
, SOL_SOCKET
, SO_SNDBUF
, &bufsize
, sizeof(bufsize
));
285 bzero((char *)&mBindSockAddr
, sizeof(mBindSockAddr
));
286 mBindSockAddr
.sin_family
= AF_INET
;
287 mBindSockAddr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
290 mBindSockAddr
.sin_port
= htons(mPortNum
);
291 if (bind(mSocket
, (struct sockaddr
*)&mBindSockAddr
, sizeof(mBindSockAddr
)) >= 0) {
294 if (!bound
) throw std::runtime_error("unable to bind udp socket\n");
298 SC_UdpCustomInPort::~SC_UdpCustomInPort()
300 mRunning
.store(false);
301 pthread_join(mThread
, NULL
);
303 if (mSocket
!= -1) closesocket(mSocket
);
305 if (mSocket
!= -1) close(mSocket
);
310 //////////////////////////////////////////////////////////////////////////////////////////////////////////
312 static void DumpReplyAddress(ReplyAddress
*inReplyAddress
)
314 printf("mSockAddrLen %d\n", inReplyAddress
->mSockAddrLen
);
315 printf("mSocket %d\n", inReplyAddress
->mSocket
);
317 printf("mSockAddr.sin_len %d\n", inReplyAddress
->mSockAddr
.sin_len
);
319 printf("mSockAddr.sin_family %d\n", inReplyAddress
->mSockAddr
.sin_family
);
320 printf("mSockAddr.sin_port %d\n", inReplyAddress
->mSockAddr
.sin_port
);
321 printf("mSockAddr.sin_addr.s_addr %d\n", inReplyAddress
->mSockAddr
.sin_addr
.s_addr
);
322 printf("mReplyFunc %p\n", inReplyAddress
->mReplyFunc
);
326 int32 Hash(ReplyAddress *inReplyAddress)
329 int32 *word = (int32*)&inReplyAddress->mSockAddr;
330 hash = Hash(inReplyAddress->mSockAddr.sin_addr.s_addr);
332 hash += inReplyAddress->mSockAddr.sin_len << 24
333 | inReplyAddress->mSockAddr.sin_family << 16
334 | inReplyAddress->mSockAddr.sin_port;
341 void udp_reply_func(struct ReplyAddress
*addr
, char* msg
, int size
);
342 void udp_reply_func(struct ReplyAddress
*addr
, char* msg
, int size
)
344 printf("->udp_reply_func\n");
345 int total
= sendallto(addr
->mSocket
, msg
, size
, (sockaddr
*)&addr
->mSockAddr
, addr
->mSockAddrLen
);
346 printf("<-udp_reply_func %d of %d\n", total
, size
);
347 if (total
< size
) DumpReplyAddress(addr
);
350 ReplyFunc
SC_UdpInPort::GetReplyFunc()
352 return udp_reply_func
;
355 void* SC_UdpInPort::Run()
357 OSC_Packet
*packet
= 0;
359 //printf("SC_UdpInPort::Run\n"); fflush(stdout);
363 packet
= (OSC_Packet
*)malloc(sizeof(OSC_Packet
));
365 packet
->mReplyAddr
.mSockAddrLen
= sizeof(sockaddr_in
);
366 int size
= recvfrom(mSocket
, buf
, kTextBufSize
, 0,
367 (struct sockaddr
*) &packet
->mReplyAddr
.mSockAddr
, (socklen_t
*)&packet
->mReplyAddr
.mSockAddrLen
);
370 //dumpOSC(3, size, buf);
373 char *data
= (char*)malloc(size
);
374 packet
->mReplyAddr
.mReplyFunc
= udp_reply_func
;
375 packet
->mSize
= size
;
376 packet
->mData
= data
;
377 packet
->mReplyAddr
.mSocket
= mSocket
;
378 memcpy(data
, buf
, size
);
379 ProcessOSCPacket(packet
, mPortNum
);
386 ReplyFunc
SC_UdpCustomInPort::GetReplyFunc()
388 return udp_reply_func
;
391 void* SC_UdpCustomInPort::Run()
393 OSC_Packet
*packet
= 0;
395 const int fd
= mSocket
;
396 const int max_fd
= fd
+1;
398 mRunning
.store(true);
399 while (mRunning
.load(boost::memory_order_consume
)) {
405 struct timeval timeout
;
407 timeout
.tv_usec
= 500000;
409 int n
= select(max_fd
, &rfds
, 0, 0, &timeout
);
410 if ((n
> 0) && FD_ISSET(fd
, &rfds
)) {
412 packet
= (OSC_Packet
*)malloc(sizeof(OSC_Packet
));
414 packet
->mReplyAddr
.mSockAddrLen
= sizeof(sockaddr_in
);
415 int size
= recvfrom(mSocket
, buf
, kTextBufSize
, 0,
416 (struct sockaddr
*) &packet
->mReplyAddr
.mSockAddr
, (socklen_t
*)&packet
->mReplyAddr
.mSockAddrLen
);
418 if (size
> 0 && mRunning
.load(boost::memory_order_consume
)) {
419 //dumpOSC(3, size, buf);
422 char *data
= (char*)malloc(size
);
423 packet
->mReplyAddr
.mReplyFunc
= udp_reply_func
;
424 packet
->mSize
= size
;
425 packet
->mData
= data
;
426 packet
->mReplyAddr
.mSocket
= mSocket
;
427 memcpy(data
, buf
, size
);
428 ProcessOSCPacket(packet
, mPortNum
);
433 FreeOSCPacket(packet
); // just in case
437 //////////////////////////////////////////////////////////////////////////////////////////////////////////
439 SC_TcpInPort::SC_TcpInPort(int inPortNum
, int inMaxConnections
, int inBacklog
)
440 : SC_ComPort(inPortNum
), mConnectionAvailable(inMaxConnections
),
444 if((mSocket
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0) {
445 throw std::runtime_error("failed to create tcp socket\n");
447 //setsockopt(mSocket, SOL_SOCKET, TCP_NODELAY);
449 bzero((char *)&mBindSockAddr
, sizeof(mBindSockAddr
));
450 mBindSockAddr
.sin_family
= AF_INET
;
451 mBindSockAddr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
452 mBindSockAddr
.sin_port
= htons(mPortNum
);
454 if(bind(mSocket
, (struct sockaddr
*)&mBindSockAddr
, sizeof(mBindSockAddr
)) < 0)
456 throw std::runtime_error("unable to bind tcp socket\n");
458 if(listen(mSocket
, mBacklog
) < 0)
460 throw std::runtime_error("unable to listen tcp socket\n");
466 void* SC_TcpInPort::Run()
470 mConnectionAvailable
.Acquire();
471 struct sockaddr_in address
; /* Internet socket address stuct */
472 int addressSize
=sizeof(struct sockaddr_in
);
473 int socket
= accept(mSocket
,(struct sockaddr
*)&address
,(socklen_t
*)&addressSize
);
475 mConnectionAvailable
.Release();
477 new SC_TcpConnectionPort(this, socket
);
483 void SC_TcpInPort::ConnectionTerminated()
485 mConnectionAvailable
.Release();
488 ReplyFunc
SC_TcpInPort::GetReplyFunc()
490 return null_reply_func
;
493 //////////////////////////////////////////////////////////////////////////////////////////////////////////
495 SC_TcpConnectionPort::SC_TcpConnectionPort(SC_TcpInPort
*inParent
, int inSocket
)
496 : SC_ComPort(0), mParent(inParent
)
502 SC_TcpConnectionPort::~SC_TcpConnectionPort()
505 closesocket(mSocket
);
509 mParent
->ConnectionTerminated();
512 void tcp_reply_func(struct ReplyAddress
*addr
, char* msg
, int size
);
513 void tcp_reply_func(struct ReplyAddress
*addr
, char* msg
, int size
)
515 sendall(addr
->mSocket
, msg
, size
);
518 ReplyFunc
SC_TcpConnectionPort::GetReplyFunc()
520 return tcp_reply_func
;
523 extern const char* gPassword
;
525 void* SC_TcpConnectionPort::Run()
527 OSC_Packet
*packet
= 0;
528 // wait for login message
534 packet
= (OSC_Packet
*)malloc(sizeof(OSC_Packet
));
536 size
= recvall(mSocket
, &msglen
, sizeof(int32
));
537 if (size
< 0) goto leave
;
539 // sk: msglen is in network byte order
540 msglen
= ntohl(msglen
);
542 char *data
= (char*)malloc(msglen
);
543 size
= recvall(mSocket
, data
, msglen
);
544 if (size
< msglen
) goto leave
;
546 packet
->mReplyAddr
.mReplyFunc
= tcp_reply_func
;
547 packet
->mSize
= msglen
;
548 packet
->mData
= data
;
549 packet
->mReplyAddr
.mSocket
= mSocket
;
550 ProcessOSCPacket(packet
, mPortNum
);
554 delete this; // ohh this could cause a crash if a reply tries to access it..
558 //////////////////////////////////////////////////////////////////////////////////////////////////////////
561 # include <sys/select.h>
565 SC_TcpClientPort::SC_TcpClientPort(int inSocket
, ClientNotifyFunc notifyFunc
, void *clientData
)
567 mClientNotifyFunc(notifyFunc
),
568 mClientData(clientData
)
571 socklen_t sockAddrLen
= sizeof(mReplySockAddr
);
573 if (getpeername(mSocket
, (struct sockaddr
*)&mReplySockAddr
, &sockAddrLen
) == -1) {
574 memset(&mReplySockAddr
, 0, sizeof(mReplySockAddr
));
575 mReplySockAddr
.sin_family
= AF_INET
;
576 mReplySockAddr
.sin_addr
.s_addr
= htonl(INADDR_NONE
);
577 mReplySockAddr
.sin_port
= htons(0);
580 #if HAVE_SO_NOSIGPIPE
582 setsockopt(mSocket
, SOL_SOCKET
, SO_NOSIGPIPE
, &sockopt
, sizeof(sockopt
));
583 #endif // HAVE_SO_NOSIGPIPE
585 if (pipe(mCmdFifo
) == -1) {
586 mCmdFifo
[0] = mCmdFifo
[1] = -1;
592 SC_TcpClientPort::~SC_TcpClientPort()
595 closesocket(mCmdFifo
[0]);
596 closesocket(mCmdFifo
[1]);
597 closesocket(mSocket
);
605 void* SC_TcpClientPort::Run()
607 OSC_Packet
*packet
= 0;
611 int cmdfd
= mCmdFifo
[0];
612 int sockfd
= mSocket
;
613 int nfds
= sc_max(cmdfd
, sockfd
) + 1;
615 bool cmdClose
= false;
617 pthread_detach(mThread
);
622 FD_SET(cmdfd
, &rfds
);
623 FD_SET(sockfd
, &rfds
);
625 if ((select(nfds
, &rfds
, 0, 0, 0) == -1) || (cmdClose
= FD_ISSET(cmdfd
, &rfds
)))
628 if (!FD_ISSET(sockfd
, &rfds
))
631 packet
= (OSC_Packet
*)malloc(sizeof(OSC_Packet
));
632 if (!packet
) goto leave
;
636 size
= recvall(sockfd
, &msglen
, sizeof(int32
));
637 if (size
< (int32
)sizeof(int32
)) goto leave
;
639 // msglen is in network byte order
640 msglen
= ntohl(msglen
);
642 packet
->mData
= (char*)malloc(msglen
);
643 if (!packet
->mData
) goto leave
;
645 size
= recvall(sockfd
, packet
->mData
, msglen
);
646 if (size
< msglen
) goto leave
;
648 memcpy(&packet
->mReplyAddr
.mSockAddr
, &mReplySockAddr
, sizeof(mReplySockAddr
));
649 packet
->mReplyAddr
.mSockAddrLen
= sizeof(mReplySockAddr
);
650 packet
->mReplyAddr
.mSocket
= sockfd
;
651 packet
->mReplyAddr
.mReplyFunc
= tcp_reply_func
;
652 packet
->mSize
= msglen
;
653 ProcessOSCPacket(packet
, mPortNum
);
663 // Only call notify function when not closed explicitly
664 if (!cmdClose
&& mClientNotifyFunc
) {
665 (*mClientNotifyFunc
)(mClientData
);
671 void SC_TcpClientPort::Close()
675 win32_pipewrite(mCmdFifo
[1], &cmd
, sizeof(cmd
));
677 size_t written
= write(mCmdFifo
[1], &cmd
, sizeof(cmd
));
678 if (written
!= sizeof(cmd
))
679 post("warning: invalid write in SC_TcpClientPort::Close");
683 ReplyFunc
SC_TcpClientPort::GetReplyFunc()
685 return tcp_reply_func
;
688 //////////////////////////////////////////////////////////////////////////////////////////////////////////
690 int recvall(int socket
, void *msg
, size_t len
)
696 int numbytes
= recv(socket
, reinterpret_cast<char*>(msg
), len
- total
, 0);
698 int numbytes
= recv(socket
, msg
, len
- total
, 0);
700 if (numbytes
<= 0) return total
;
702 msg
= (void*)((char*)msg
+ numbytes
);
707 int recvallfrom(int socket
, void *msg
, size_t len
, struct sockaddr
*fromaddr
, int addrlen
)
712 socklen_t addrlen2
= addrlen
;
714 int numbytes
= recvfrom(socket
, reinterpret_cast<char*>(msg
), len
- total
, 0, fromaddr
, &addrlen2
);
716 int numbytes
= recvfrom(socket
, msg
, len
- total
, 0, fromaddr
, &addrlen2
);
718 if (numbytes
< 0) return total
;
720 msg
= (void*)((char*)msg
+ numbytes
);
725 int sendallto(int socket
, const void *msg
, size_t len
, struct sockaddr
*toaddr
, int addrlen
)
731 int numbytes
= sendto(socket
, reinterpret_cast<const char*>(msg
), len
- total
, 0, toaddr
, addrlen
);
733 int numbytes
= sendto(socket
, msg
, len
- total
, 0, toaddr
, addrlen
);
735 //printf("numbytes %d total %d len %d\n", numbytes, total, len);
737 printf("******* errno %d %s\n", errno
, strerror(errno
));
741 msg
= (void*)((char*)msg
+ numbytes
);
746 int sendall(int socket
, const void *msg
, size_t len
)
751 #if HAVE_MSG_NOSIGNAL
752 int flags
= MSG_NOSIGNAL
;
755 #endif // HAVE_MSG_NOSIGNAL
757 int numbytes
= send(socket
, reinterpret_cast<const char*>(msg
), len
- total
, flags
);
759 int numbytes
= send(socket
, msg
, len
- total
, flags
);
761 if (numbytes
< 0) return total
;
763 msg
= (void*)((char*)msg
+ numbytes
);
768 //////////////////////////////////////////////////////////////////////////////////////////////////////////