pax_global_header00006660000000000000000000000064125723766570014536gustar00rootroot0000000000000052 comment=5de4ef7d80bed7b8a499f506f5cce5db9bc2e4cb pd-iemnet-0.2.1/000077500000000000000000000000001257237665700134205ustar00rootroot00000000000000pd-iemnet-0.2.1/.gitignore000066400000000000000000000000351257237665700154060ustar00rootroot00000000000000*.o *.pd_linux *.so *~ .svn/ pd-iemnet-0.2.1/.travis.yml000066400000000000000000000016501257237665700155330ustar00rootroot00000000000000language: c env: global: - secure: "H+FS0KWYGx4JBMcPdhhJus9LgFhh5luIU4rfWl6Fsh4q0VJmT1tSO3KYlEQYkenS4xX/sUtN/Yus1b8L0MkuM3akEEPAA26Up9leFsarIQrD3dGYmoNQ4R2eG1Et8hoNwQwXQ1f30wrqfykVK+83rzqSlpoz+nhTBKZNYC7tfn0=" - COVERITY_SCAN_BRANCH_PATTERN="coverity_scan" - COVERITY_SCAN_NOTIFICATION_EMAIL="zmoelnig@users.sourceforge.net" - COVERITY_SCAN_BUILD_COMMAND="make" matrix: include: - compiler: clang - compiler: gcc env: - COVERITY_SCAN_PROJECT_NAME="$TRAVIS_REPO_SLUG" before_install: - sudo apt-get update -qq - sudo apt-get install -qq puredata-dev before_script: # implement Coverity Scan with before_script instead of addons.coverity_scan # to work around too-early quota check by the coverity_scan addon - if [[ -n $COVERITY_SCAN_PROJECT_NAME ]] ; then curl -s 'https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh' | bash || true ; fi script: - make pd-iemnet-0.2.1/AUTHORS000066400000000000000000000001141257237665700144640ustar00rootroot00000000000000Roman Häfeli Olaf Matthes Martin Peach Miller Puckette IOhannes m zmölnig pd-iemnet-0.2.1/ChangeLog000066400000000000000000000611651257237665700152030ustar00rootroot000000000000002015-09-01 12:00 zmoelnig * iemnet-v0.2 got rid of threaded receiver - simplifies code - fixes a couple of stability bugs - compiles again on W32 one-true-brace-style reproducible build 2010-10-11 16:04 zmoelnig * tcpreceive.c, udpreceive.c: use SO_REUSEPORT (if available during compile-time) 2010-10-11 15:34 zmoelnig * .: svn:ignore all *.pd_linux 2010-10-11 12:15 zmoelnig * AUTHORS: authors illiterati 2010-10-11 12:13 zmoelnig * ChangeLog, NEWS: ChangeLog and NEWS files with bugs bunny and bill clinton 2010-10-11 12:04 zmoelnig * udpserver.c: at least accept one(1) client 2010-10-11 12:03 zmoelnig * iemnet.h: these debug things 2010-10-08 22:11 rdz * tcpserver-help.pd: added 'port' for outlet #4 2010-10-08 22:08 rdz * udpserver-help.pd: added help for [udpserver] 2010-10-08 21:57 rdz * tcpclient-help.pd, tcpreceive-help.pd, tcpsend-help.pd, tcpserver-help.pd, udpreceive-help.pd, udpsend-help.pd: added a 'check also:' section where applicable 2010-10-08 21:43 rdz * udpclient-help.pd: added help for [udpclient] 2010-10-08 20:53 rdz * tcpserver-help.pd: corrected NOTE: there is no outlet 6. made outlet counting consistent (start at 1). 2010-10-06 20:06 zmoelnig * tcpclient-help.pd, tcpreceive-help.pd, tcpserver-help.pd, udpreceive-help.pd, udpsend-help.pd: more iemnet specifics 2010-10-05 22:26 rdz * iemnet-meta.pd: made iemnet-meta.pd comply with the libname-meta.pd format 2010-10-02 20:39 rdz * tcpserver-help.pd: added description to the 'bufsize' status message 2010-10-02 20:34 rdz * tcpclient-help.pd, tcpreceive-help.pd, tcpsend-help.pd, tcpserver-help.pd: updated help of [tcpsend]/[tcpreceive] to reflect their current behaviour 2010-10-02 19:46 rdz * tcpclient-help.pd: updated help to reflect current behaviour of [tcpclient] 2010-10-02 19:15 rdz * tcpserver-help.pd: updated help to reflect [tcpserver]'s current behaviour 2010-09-20 15:06 zmoelnig * iemnet.h: global debuglevel 2010-09-20 14:35 zmoelnig * iemnet_receiver.c: more debugging in the tick 2010-09-20 13:31 zmoelnig * Makefile: added DEBUG_CFLAGS 2010-09-20 13:19 zmoelnig * iemnet.c: less verbose when changing debuglevel 2010-09-20 13:14 zmoelnig * iemnet.c, iemnet.h, iemnet_data.c, iemnet_receiver.c, iemnet_sender.c, tcpclient.c, tcpreceive.c, tcpsend.c, tcpserver.c, udpclient.c, udpreceive.c, udpsend.c, udpserver.c: debugging levels 2010-09-15 12:37 mescalinum * Makefile: remove -mcpu/-mtune flags as it breaks x64 build. we should eventually figure a way of determining automatically the CPU, but 'uname -m' doesn't tell the truth 2010-09-14 08:53 zmoelnig * iemnet_receiver.c: receive in nonblocking mode 2010-09-14 08:39 zmoelnig * iemnet_receiver.c: on the way to thread safety...(?) a number of new mutexes to protect what is there to protect. avoid deadlocks when using the big pd-lock 2010-09-13 13:48 zmoelnig * udpserver.c: more DEBUG; alternative algorithm to add clients with a connection-less protocol it's a bit hard to know which clients are connected to a server... 2010-09-13 13:43 zmoelnig * iemnet_receiver.c, udpreceive.c: nada: whitespace 2010-09-13 13:38 zmoelnig * iemnet_receiver.c: removed the "return" at the beginning of iemnet__receiver_destroy() it looks like i put it there for debugging something; but i cannot remember now exactly... 2010-09-09 13:53 zmoelnig * iemnet_receiver.c: more debug output 2010-09-09 13:52 zmoelnig * udpclient.c: ... 2010-08-27 09:15 zmoelnig * tcpserver.c: get rid o fwarning in sprintf() 2010-08-23 14:35 zmoelnig * iemnet_receiver.c: on read termination read the status variables in a protected area 2010-08-23 12:46 zmoelnig * iemnet.c, iemnet_data.c, iemnet_receiver.c, iemnet_sender.c, udpserver.c: use malloc() rather than getbytes(); use pthread_exit(); 2010-08-22 11:57 zmoelnig * udpserver.c: more support for udpserver 2010-08-20 17:19 zmoelnig * udpsend.c: fixed reentrancy issue 2010-08-20 16:54 zmoelnig * iemnet_data.c, iemnet_sender.c: fixed bugs in multithreading code 2010-08-20 16:20 zmoelnig * iemnet.h: in DEBUG mode, define IEMNET_HAVE_DEBUG 2010-08-20 14:32 zmoelnig * iemnet_data.c: reindentated; add some comments 2010-08-20 14:12 zmoelnig * iemnet_sender.c: more DEBUGs; clear memory before freeing it 2010-08-20 14:11 zmoelnig * iemnet_data.c: added more DEBUGs 2010-08-20 14:09 zmoelnig * udpreceive.c: output sender address 2010-08-09 09:22 zmoelnig * iemnet_data.c: allow resizing of NULL-floatlists trying to resize a NULL-floatlist, will create a new one with the required size 2010-07-14 17:52 zmoelnig * udpsend.c: fixed crasher bug when printing "[udpsend] not connected" 2010-04-07 14:45 zmoelnig * iemnet.c, iemnet.h, tcpclient.c, tcpreceive.c, tcpserver.c: iemnet__streamout() takes an argument telling us whether to serialize or not (non-serialization might be useful for proxies) 2010-04-07 14:29 zmoelnig * udpserver.c: first working prototype - still loads of problems the socket outlet doesn't make any sense (remove it?) disconnecting kills the receiver thread! 2010-04-07 14:27 zmoelnig * iemnet.h, iemnet_receiver.c, tcpclient.c, tcpreceive.c, tcpserver.c, udpclient.c, udpreceive.c: new receiver callback: chunk2list has to be handled by client 2010-04-07 14:24 zmoelnig * iemnet_sender.c: sender now optionally uses sendto() if the chunk has an address/port specified, sendto() is used; else the default send() on the socket is used 2010-04-07 14:22 zmoelnig * iemnet_data.h: nice documentation (this file is not so private any more) 2010-04-01 12:22 zmoelnig * Makefile: don't need verbose auto-vectorizer 2010-04-01 12:21 zmoelnig * tcpserver.c: floatlist should be handled in the object 2010-04-01 12:21 zmoelnig * iemnet_receiver.c: cleanup queue in destructor 2010-04-01 12:18 zmoelnig * iemnet_data.c: check whether queue is !NULL before pushing/popping 2010-04-01 11:20 zmoelnig * tcpserver.c: call sender_destroy/receiver_destroy before cleaning up socketreceiver 2010-04-01 10:20 zmoelnig * iemnet.h: use directly rather than for getting needed types 2010-04-01 09:51 zmoelnig * iemnet.h: include stdlib.h on OSX (10.4) you cannot use INADDR_ANY without types, which are not provided by the header that defines INADDR_ANY... 2010-04-01 09:33 zmoelnig * tests/sequence/01_server.pd: display the queue status 2010-04-01 09:24 zmoelnig * tcpsend.c: fixed objName for tcpsend 2010-04-01 09:14 zmoelnig * build/w32-vs2003/iemnet.vcproj, iemnet.c: updated M$VC project 2010-04-01 09:03 zmoelnig * udpserver.c: added note about udpserver not being useable yet 2010-04-01 09:01 zmoelnig * udpserver.c: use error() for errors 2010-04-01 07:22 zmoelnig * Makefile, udpserver.c: non-functional crashy copy of tcpserver for udp 2010-04-01 07:21 zmoelnig * udpreceive.c: status outlet and forgotten struct member... 2010-04-01 07:21 zmoelnig * iemnet_sender.c: iemnet__sender_destroy() now also closes the socket 2010-04-01 07:21 zmoelnig * udpclient.c: use error instead of post 2010-04-01 07:21 zmoelnig * iemnet.c, iemnet.h, tcpclient.c, tcpreceive.c, tcpsend.c, tcpserver.c, udpclient.c, udpreceive.c, udpsend.c: exporting symbols; using objName 2010-04-01 07:20 zmoelnig * iemnet.c, iemnet.h: convenience function for outputting the socket 2010-04-01 07:20 zmoelnig * iemnet.c, iemnet.h: convenience function for outputting the number of connections 2010-04-01 07:20 zmoelnig * tcpreceive-help.pd, tcpreceive.c: tcpclient fixes and features fixed the callback (API changed but due to cast this has gone unnoticed) featured settable ports (and now creation failure is port is taken) 2010-04-01 07:20 zmoelnig * tcpclient.c: made connection thread safe the connection thread modifies the object's state (and calls clock_delay()) since this is not thread safe, it is now protected by sys_lock() NOTE1: i remember someone saying that clock_delay() is thread safe NOTE2: this might still crash if the object is deleted before while the thread is executing 2010-04-01 07:20 zmoelnig * tcpserver.c: removed duplicate inclusion is already included in iemnet.h 2010-03-31 13:44 zmoelnig * tests, tests/sequence, tests/sequence/01_client.pd, tests/sequence/01_server.pd: simple test, whether sequences qppear in the right order 2010-03-31 09:21 zmoelnig * tcpserver.c: made "target" persistent, even if clients disconnect added "targetsocket" to specify the target via socket 2010-03-31 08:58 zmoelnig * iemnet.c, iemnet.h, tcpclient.c, tcpreceive.c, tcpserver.c: output the data of stream-based objects in a serialized form 2010-03-31 08:51 zmoelnig * FEATURES.txt, README.txt: features sheet 2010-03-31 08:04 zmoelnig * tcpserver.c: query the server port especially useful when autoassigning ports (port=0) 2010-03-30 12:45 zmoelnig * tcpserver.c: tcpserver now does not fail to create if port is already in use with the "port" message, the listening port can be changed at runtime (LATER we also want to query the port...) 2010-03-30 11:51 zmoelnig * tcpclient.c: avoid double registration of tcpclient 2010-03-30 10:54 zmoelnig * build/w32-vs2003/iemnet.vcproj: updated M$VC project 2010-03-30 10:52 zmoelnig * iemnet.h, tcpserver.c: added "target" method to tcpserver, to specify how to send ordinary lists target 0: broadcast target >0: send to specified client target <0: send not to specified client (but all others) 2010-03-30 09:46 zmoelnig * iemnet_data.c, iemnet_data.h, iemnet_receiver.c, iemnet_sender.c, tcpclient.c, tcpserver.c: query queue sizes with [tcpclient] use [bang( with [tcpserver] use [client ( 2010-03-30 09:06 zmoelnig * Makefile, iemnet.h, iemnet_data.c, iemnet_data.h: inline code documentation 2010-03-30 07:36 zmoelnig * Makefile, iemnet.c, iemnet.h, iemnet_data.c, iemnet_data.h, iemnet_receiver.c, iemnet_sender.c: split core library into separate files 2010-03-29 17:32 zmoelnig * build/w32-vs2003/iemnet.vcproj, iemnet.h, tcpreceive.c: made it compile on w32 again 2010-03-29 17:30 zmoelnig * tcpreceive.c, tcpsend.c, udpreceive.c, udpsend.c: replaced &s_... by gensym("...") this time it's the right lib 2010-03-29 17:18 zmoelnig * tcpserver.c: disable DEBUG 2010-03-29 17:11 zmoelnig * tcpclient.c, tcpserver.c: output additional data just like with mrpeach's objects 2010-03-29 16:15 zmoelnig * tcpclient.c: use error() rather than post() where appropriate 2010-03-29 16:13 zmoelnig * tcpclient.c: proper handling of remote disconnect 2010-03-29 14:10 zmoelnig * iemnet.c, tcpserver.c: provide feedback to Pd main-thread whether sender-thread still exists 2010-03-29 13:37 zmoelnig * iemnet.c: sender/receiver dtors can now be called recursively without double freeing resources (hopefully) 2010-03-29 13:07 zmoelnig * iemnet.c, tcpclient.c, tcpserver.c: clean up more properly on disconnect disconnecting has the awful tendency to trigger itself; for now, this is handled in the calling object's code, but later iemnet_(sender|receiver) should take care themselves 2010-03-29 13:04 zmoelnig * NOTES.txt: remind me of doing tests 2010-03-27 08:55 zmoelnig * iemnet.c: no need to lock the entire Pd-process 2010-03-26 14:36 zmoelnig * iemnet-meta.pd: iemnet-meta.pd is needed for "make dist" this should be properly documented within the Makefile... 2010-03-26 14:35 zmoelnig * Makefile: make cleaner 2010-03-26 14:35 zmoelnig * NOTES.txt, README.txt: more mission and scratchpad 2010-03-26 14:35 zmoelnig * iemnet.c: sys_lock() before calling clock_delay() LATER: think about using sys_trylock 2010-03-26 14:35 zmoelnig * tcpclient.c, udpclient.c: output server address 2010-03-26 14:34 zmoelnig * Makefile, udpclient.c: a simple udpclient bidirectional communication using UDP 2010-03-26 14:34 zmoelnig * tcpclient.c, tcpreceive.c, tcpsend.c, tcpserver.c, udpreceive.c, udpsend.c: proper use of DEBUG use DEBUG() directly rather than "#ifdef DEBUG" 2010-03-26 14:34 zmoelnig * udpsend.c: whitespaces... 2010-03-26 14:33 zmoelnig * udpreceive~.c, udpsend~-help.pd, udpsend~.c, udpsend~.h: no more audio-over-net objects use AOO (Audio Over OSC) or the like for such things... 2010-03-26 14:33 zmoelnig * Makefile, udpsend.c: udpsend 2010-03-26 14:33 zmoelnig * udpreceive.c: fix description: udpreceive is really a server 2010-03-26 14:32 zmoelnig * tcpserver.c: output the sending host 2010-03-26 14:32 zmoelnig * Makefile, udpreceive.c: udpreceive seems to work... 2010-03-26 14:32 zmoelnig * tcpserver.c: compatibility with mrpeach; convenience re-add all those stupid outlets. use convenience functions to send data to these outlets 2010-03-26 14:32 zmoelnig * iemnet.c, iemnet.h: convenience functions these probably should go into a separate file 2010-03-26 14:31 zmoelnig * tcpsend.c: use DEBUG() 2010-03-26 14:31 zmoelnig * iemnet.c, iemnet.h, tcpclient.c, tcpserver.c: changed API of read-callback the callback will provide the raw data chunk as well (easier to add more data) 2010-03-25 11:36 zmoelnig * iemnet.c, iemnet.h: DEBUG mechanism 2010-03-25 11:35 zmoelnig * README.txt: more missions 2010-03-25 11:34 zmoelnig * README.txt: mission statement 2010-03-25 08:29 zmoelnig * Makefile: included tcp* objects in Makefile 2010-03-25 08:28 zmoelnig * iemnet.h: most of the tcp-objects seem to work now; performance increase as measured until now is great :-) 2010-03-25 08:28 zmoelnig * iemnet.c, tcpclient.c, tcpreceive.c, tcpsend.c, tcpserver.c: most of the tcp-objects seem to work now; performance increase as measured until now is great :-) 2010-03-24 22:47 eighthave * Makefile: added include path for Pd-extended.app include folder to include path, after the -I$(PD_PATH)/src/ so it'll only use the headers inside the Pd-extended.app if the source is not specified 2010-03-24 17:39 zmoelnig * iemnet.c, tcpclient.c: on M$VC we only build libraries (and the autoregistration doesn't work) 2010-03-24 17:38 zmoelnig * build/w32-vs2003/iemnet.vcproj: removed the "shared.c" 2010-03-24 17:25 zmoelnig * iemnet.h, tcpserver.c: fixed M$VC preprocessor code 2010-03-24 17:20 zmoelnig * Makefile, iemnet.c, iemnet.h, shared.c, tcpclient.c, tcpserver.c: automatic calling 2010-03-24 16:41 zmoelnig * shared.c: cleaned up 2010-03-24 16:40 zmoelnig * tcpclient.c: check for validity before disconnecting (and invalidate pointers after) 2010-03-24 16:31 zmoelnig * shared.c: call shutdown before closesocket() 2010-03-24 15:58 zmoelnig * iemnet.c, iemnet.h, shared.c, tcpclient.c, tcpserver.c: made it compile (and run) on w32 2010-03-24 15:57 zmoelnig * build, build/w32-vs2003, build/w32-vs2003/iemnet.sln, build/w32-vs2003/iemnet.vcproj: w32 project 2010-03-24 15:24 zmoelnig * Makefile, shared.c, tcpclient.c, tcpserver.c: a first client 2010-03-24 12:09 zmoelnig * iemnet.h, shared.c, tcpserver.c: kind of works now: we can dump about 500MB within 5secs into tcpserver on lo 2010-03-24 12:09 zmoelnig * Makefile: only build tcpserver for now 2010-03-23 19:26 zmoelnig * shared.c: clock-based interfacing with Pd's main thraed 2010-03-23 19:05 zmoelnig * iemnet.h, shared.c, tcpserver.c: hmm, less crashes; threads hang 2010-03-23 17:49 zmoelnig * Makefile, iemnet.h, shared.c, tcpserver.c: factored out code into "shared"; it's still rather unstable... 2010-03-23 13:36 zmoelnig * tcpserver.c: cleaned up 2010-03-23 12:10 zmoelnig * Makefile: Makefile (taken from ext13) 2010-03-23 11:54 zmoelnig * .: forked mrpeach's "net" 2010-03-22 20:12 mrpeach * Changed valid-stream output to be a signal output. Moved all post()s out of the perform routine. Updated help patch and version. 2010-03-22 15:29 zmoelnig * check for NULL-pointer in destructor 2010-03-16 17:22 mrpeach * Output valid state only when it changes. 2010-03-16 16:42 mrpeach * Added an outlet to udpreceive~ to indicate valid audio. Ouput address and port only if changed. Updated version and help patch. 2010-03-11 21:04 mrpeach * Updfated version number and help patch. 2010-03-11 19:28 mrpeach * Added a "TAG!" identifier field to the tag so it can be verified as a tag. This should help prevent crashes in case of dropped packets. 2010-03-09 17:31 mrpeach * Moved client-specific parameters into a single t_tcpserver_socketreceiver struct. 2010-03-09 10:28 zmoelnig * fixing bug #2966186 2010-03-02 17:44 mrpeach * Added a verbosity method to stop [tcpclient] printing in the main window every time it connects/disconnects. Updated the help patch to match. 2010-02-24 18:37 mrpeach * Corrected some error messages, check for EINVAL after recvfrom(), to try to find out why it happens... 2010-01-20 19:41 mrpeach * Added SO_BROADCAST so you can actually broadcast with a .255 address... 2010-01-18 17:41 mrpeach * use unix line endings 2010-01-18 17:25 mrpeach * Make the connection thread detached and don't refer to its struct directly, check for thread creation errors. 2010-01-18 04:31 mrpeach * Use NULL instead of 0 to reset thread pointer so maybe now MinGW can compile it...removed unused symbols 2010-01-15 18:53 mrpeach * Added include for ws2tcpip.h for socklen_t for _WIN32 2010-01-14 20:26 mrpeach * Don't need float_cast.h anymore, using the flint union with ntohl/htonl instead. 2010-01-14 20:24 mrpeach * Always send in network byte order for all architectures. UDP receiving socket doesn't need to be non-blocking (I think...). Cleaned up help patch. 2010-01-14 20:21 mrpeach * Changed int optLen to socklen_t to avoid signedness warning 2010-01-13 21:54 mrpeach * Fixed header files for _WIN32 2010-01-12 18:58 mrpeach * Block size is settable by creation argument. Buffer size message is specified in frames. Info message gives some more info. Channels transmitted can be set to zero. Cleaned up help patch. 2010-01-11 16:56 mrpeach * Added "unix" to the test for "UNIX". 2010-01-11 14:27 mrpeach * help patch for udpsend~ and udpreceive~ 2010-01-11 14:25 mrpeach * Versions of netsend~ for udp. 2010-01-04 16:49 mrpeach * Had the wrong #include for ioctl... 2010-01-02 20:50 mrpeach * Changed MSW to _WIN32. Added tcpserver_send_buffer_avaliable_for_client() using SIOCOUTQ ioctl in linux to see if send buffer has any room left. Apparently no equivalent exists for BSD or Windows. 2010-01-02 20:04 mrpeach * Changed MSW to _WIN32 2010-01-02 20:03 mrpeach * Changed MSW to _WIN32 2010-01-02 19:59 mrpeach * Changed MSW to _WIN32 2010-01-02 19:52 mrpeach * Changed MSW to _WIN32 2010-01-02 19:51 mrpeach * Changed MSW to _WIN32 2009-11-29 17:37 mrpeach * Sender threads are now created in the detached state so their resources will be freed when the threads complete. This appears to stop the accumulation of handles on WinXP at least. 2009-11-28 21:38 mrpeach * Removed duplicate send, added threaded send for files, and also send whenever buffer is full (65536 bytes) for incoming lists (although [tcpserver] is unlikely to be fed lists that long) 2009-11-12 22:16 mrpeach * Using pthreads to send each message to each client in its own thread. This should eliminate hangups when clients disappear halfway through, and increase responsiveness of Pd with [tcpserver]. Messages are sent as one unit instead of byte-by-byte. Select() is no longer used to check for available space in the buffer. 2009-04-08 19:48 mrpeach * Oops, I had forgotten to add the default timeout of 1000us. 2009-04-08 19:34 mrpeach * Added timeout message to set send timeout in microseconds, defaults to 1000. Changed help patch to match. 2009-04-08 18:35 mrpeach * Added [timeout( message to set microsecond timeout for send. This gives time for unusually small buffers to clear. Set default timeout to 1000us. Also prints a message if the whole send didn't complete. Updated help patch to match. 2009-03-09 16:01 mrpeach * The 'sent' message now contains client number, bytes sent, socket number. Empty 'send' message triggers list of client messages on right outlet. Empty socket number message causes a client message on right outlet. Help patch updated. 2009-03-04 22:33 mrpeach * Changed send routine to send one byte at a time and output number of bytes sent, so it won't block if the other end disappears. Also settable buffer size. Help path updated. 2009-03-02 17:55 mrpeach * Fixed some warnings about signed/unsigned variables. 2009-03-02 17:01 mrpeach * Fixed a bug that prevented the send routine from leaving the loop when no more data can be sent. Now it won't hang if you try sending to a recently disconnected client, honest! 2009-03-02 03:41 mrpeach * tcpserver_send_buf: send only one byte at a time into the buffer to avoid buffer overflow. This should not slow the whole thing down too much since we're already passing things one byte at a time. 2009-03-01 21:56 mrpeach * Added a [clientbuf( message to set the send buffer size for that client. Also the [client( message will output the current buffer size as well as the socket and ip for that client. Help patch updated. 2009-02-24 21:07 mrpeach * Updated help files to reflect new [tcpserver], cleaned up a bit more. 2009-02-24 21:06 mrpeach * Adds a status outlet which currently gives info about connected clients and the amount of sent data. 2009-02-23 20:58 mrpeach * Fixed select call so it works properly 2009-02-22 23:39 mrpeach * include errno.h for linux 2009-02-22 22:36 mrpeach * Removed some commented-out stuff 2009-02-22 22:25 mrpeach * Checks to see if a socket can be written to before sending. If not, prints a message to the pd window and doesn't send the data. 2008-11-05 19:58 mrpeach * Updated to add port number to list on right outlet 2008-11-05 19:58 mrpeach * Added port number output to ip list on right outlet as suggested by zmoelnig 2008-11-05 19:35 mrpeach * Updated to add port number on ip (right) outlet 2008-11-05 19:34 mrpeach * Added port number to ip outlet as suggested by zmoelnig 2008-11-05 19:06 mrpeach * Added broadcast permission to sockets as suggested by zmoelnig's patch 2221504 2008-06-18 17:30 mrpeach * Clarify what SO_REUSEADDR is for, no code changes. 2008-05-07 09:56 zmoelnig * removed svn:executable-flag 2008-03-27 19:56 mrpeach * No limit on sendable file size. 2008-03-20 15:57 mrpeach * Updated with dump message 2008-03-20 15:50 mrpeach * Added dump message for hexdump of received characters to main window. Added #include for u_long define. 2008-01-21 14:09 mrpeach * Applied W.Ritsch's patch to fix sign error with input > 127 2007-08-06 22:18 mrpeach * Closing socket should actually work now. Before it was just removing it from the list. 2007-08-02 15:56 mrpeach * Added disconnectclient and disconnectsocket methods so server can close connections too. 2007-07-23 16:48 mrpeach * Removed unused static binbuf that caused occasional crashes when reinstantiating the object. Thanks IOhannes for pointing it out! 2007-06-20 21:10 mrpeach * Updated 2007-06-20 20:31 mrpeach * Implemented IOhannes' list send 2006-12-12 09:07 zmoelnig * removed the "break;" statement in the broadcast() code to enable broadcasting to all connected clients (and not jsut the first one) 2006-12-04 20:18 mrpeach * make sure bytes > 127 are not interpreted as negative. 2006-12-04 20:17 mrpeach * make sure bytes >127 are not interpreted as negative. 2006-12-01 16:50 mrpeach * Use sprintf_s instead of snprintf if _MSC_VER defined 2006-11-28 16:44 mrpeach * changed MAX_PATH to FILENAME_MAX. 2006-11-28 16:43 mrpeach * changed MAX_PATH to FILENAME_MAX 2006-11-07 21:58 mrpeach * test file for net object help patches 2006-11-07 21:57 mrpeach * added send filename 2006-11-07 21:21 mrpeach * removed declspec 2006-11-07 21:20 mrpeach * added file send 2006-08-24 06:51 mrpeach * Renamed files without x_net_ prefix. Removed extra copies of tcpserver and tcpclient 2006-08-17 05:33 eighthave * added mrpeach targets and added missing header to get things compiling on Mac OS X 2006-08-16 20:22 mrpeach * Added the net, osc and sqosc~ directories pd-iemnet-0.2.1/FEATURES.txt000066400000000000000000000035471257237665700154100ustar00rootroot00000000000000iemnet - networking for Pd ========================== A general: iemnet objects provide a low-level interface (OSI-5 transport layer) to networking from within Pd. iemnet tries to do only one thing (transmitting data over the internet), but it tries to do it good. A1 data data passed over the network has to be given as "list of bytes". in Pd-speak these are "list"s, containing only floating point numbers whoses values must be integer and in the range 0..255. you have to take care of that yourself. if you don't (e.g. trying to send symbols, fractional numbers, out of range numbers), you are to blame. in order to send more complex data, you have to wrap them into an application layer protocol, such as Open Sound Control (OSC). you can find objects to convert OSC messages to/from messages understood by iemnet objects in Martin Peaches great "osc" library. A2 threading iemnet makes heavy use of threading. this means that sending data (to the internet), receiving data (from the internet) and processing datat (within Pd) can run in parallel. this means that you won't get audio dropouts if the network is slow because your your neighbour is downloading videos. if you have a multi-core (SMP) system, threads can utitlize this. if you don't have a multi-core (SMP) system, you still benefit from the threading approach. B TCP/IP objects B1 [tcpserver] listens on a port for incoming messages if the port is already occupied, you are provided feedback so you can react the port can be changed at runtime you can let the system chose an available port for you (and you can query it) passing only a list (without the "send ", "client " or "broadcast" prefix) specifies only the payload (data). the target can be set with the "target" message ("target 0" means "broadcast", "target " will send to "client " if id>0 and to all but "client " if id<0 pd-iemnet-0.2.1/LICENSE.txt000066400000000000000000000355641257237665700152600ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS pd-iemnet-0.2.1/Makefile000066400000000000000000000363471257237665700150750ustar00rootroot00000000000000## Pd library template version 1.0.11 # For instructions on how to use this template, see: # http://puredata.info/docs/developer/MakefileTemplate LIBRARY_NAME = iemnet # add your .c source files, one object per file, to the SOURCES # variable, help files will be included automatically, and for GUI # objects, the matching .tcl file too SOURCES = tcpserver.c tcpclient.c tcpsend.c tcpreceive.c udpreceive.c udpsend.c udpclient.c udpserver.c SHARED_SOURCES = iemnet.c iemnet_data.c iemnet_receiver.c iemnet_sender.c SHARED_HEADERS = iemnet_data.h iemnet.h # list all pd objects (i.e. myobject.pd) files here, and their helpfiles will # be included automatically PDOBJECTS = udpsndrcv.pd # example patches and related files, in the 'examples' subfolder #EXAMPLES = bothtogether.pd # manuals and related files, in the 'manual' subfolder #MANUAL = manual.txt # if you want to include any other files in the source and binary tarballs, # list them here. This can be anything from header files, test patches, # documentation, etc. README.txt and LICENSE.txt are required and therefore # automatically included EXTRA_DIST = ChangeLog FEATURES.txt NOTES.txt LIBS_windows=-lpthread #overriding the datestring # run `make CPPFLAGS="-DBUILD_DATE='\"somewhen in August\"'"` #------------------------------------------------------------------------------# # # things you might need to edit if you are using other C libraries # #------------------------------------------------------------------------------# ALL_CFLAGS = -I"$(PD_INCLUDE)" ALL_LDFLAGS = SHARED_LDFLAGS = ALL_LIBS = #------------------------------------------------------------------------------# # # you shouldn't need to edit anything below here, if we did it right :) # #------------------------------------------------------------------------------# # these can be set from outside without (usually) breaking the build CFLAGS := -Wall -Wno-unused -W -g # get library version from meta file LIBRARY_VERSION = $(shell sed -n 's|^\#X text [0-9][0-9]* [0-9][0-9]* VERSION \(.*\);|\1|p' $(LIBRARY_NAME)-meta.pd) ALL_CFLAGS += -DPD -DVERSION='"$(LIBRARY_VERSION)"' PD_INCLUDE = $(PD_PATH)/include/pd # where to install the library, overridden below depending on platform prefix = /usr/local libdir = $(prefix)/lib pkglibdir = $(libdir)/pd-externals objectsdir = $(pkglibdir) INSTALL = install INSTALL_PROGRAM = $(INSTALL) -p -m 644 INSTALL_DATA = $(INSTALL) -p -m 644 INSTALL_DIR = $(INSTALL) -p -m 755 -d ALLSOURCES := $(SOURCES) $(SOURCES_android) $(SOURCES_cygwin) $(SOURCES_macosx) \ $(SOURCES_iphoneos) $(SOURCES_linux) $(SOURCES_windows) DISTDIR=$(LIBRARY_NAME)-$(LIBRARY_VERSION) ORIGDIR=pd-$(LIBRARY_NAME:~=)_$(LIBRARY_VERSION) UNAME := $(shell uname -s) ifeq ($(UNAME),Darwin) CPU := $(shell uname -p) ifeq ($(CPU),arm) # iPhone/iPod Touch SOURCES += $(SOURCES_iphoneos) EXTENSION = pd_darwin SHARED_EXTENSION = dylib OS = iphoneos PD_PATH = /Applications/Pd-extended.app/Contents/Resources IPHONE_BASE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin CC=$(IPHONE_BASE)/gcc CPP=$(IPHONE_BASE)/cpp CXX=$(IPHONE_BASE)/g++ ISYSROOT = -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk IPHONE_CFLAGS = -miphoneos-version-min=3.0 $(ISYSROOT) -arch armv6 OPT_CFLAGS = -fast -funroll-loops -fomit-frame-pointer ALL_CFLAGS := $(IPHONE_CFLAGS) $(ALL_CFLAGS) ALL_LDFLAGS += -arch armv6 -bundle -undefined dynamic_lookup $(ISYSROOT) SHARED_LDFLAGS += -arch armv6 -dynamiclib -undefined dynamic_lookup $(ISYSROOT) ALL_LIBS += -lc $(LIBS_iphoneos) STRIP = strip -x DISTBINDIR=$(DISTDIR)-$(OS) else # Mac OS X SOURCES += $(SOURCES_macosx) EXTENSION = pd_darwin SHARED_EXTENSION = dylib OS = macosx PD_PATH = /Applications/Pd-extended.app/Contents/Resources OPT_CFLAGS = -ftree-vectorize # build universal 32-bit on 10.4 and 32/64 on newer ifeq ($(shell uname -r | sed 's|\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*|\1|'), 8) FAT_FLAGS = -arch ppc -arch i386 -mmacosx-version-min=10.4 else FAT_FLAGS = -arch i386 -arch x86_64 -mmacosx-version-min=10.4 SOURCES += $(SOURCES_iphoneos) endif ALL_CFLAGS += $(FAT_FLAGS) -fPIC ifneq ($(strip $(realpath /sw/include)),) ALL_CFLAGS += -I/sw/include endif # if the 'pd' binary exists, check the linking against it to aid with stripping BUNDLE_LOADER = $(shell test ! -e $(PD_PATH)/bin/pd || echo -bundle_loader $(PD_PATH)/bin/pd) ALL_LDFLAGS += $(FAT_FLAGS) -bundle $(BUNDLE_LOADER) -undefined dynamic_lookup ifneq ($(strip $(realpath /sw/lib)),) ALL_LDFLAGS += -L/sw/lib endif SHARED_LDFLAGS += $(FAT_FLAGS) -dynamiclib -undefined dynamic_lookup \ -install_name @loader_path/$(SHARED_LIB) -compatibility_version 1 -current_version 1.0 ALL_LIBS += -lc $(LIBS_macosx) STRIP = strip -x DISTBINDIR=$(DISTDIR)-$(OS) # install into ~/Library/Pd on Mac OS X since /usr/local isn't used much pkglibdir=$(HOME)/Library/Pd endif endif # Tho Android uses Linux, we use this fake uname to provide an easy way to # setup all this things needed to cross-compile for Android using the NDK ifeq ($(UNAME),ANDROID) CPU := arm SOURCES += $(SOURCES_android) EXTENSION = pd_linux SHARED_EXTENSION = so OS = android PD_PATH = /usr NDK_BASE := /usr/local/android-ndk NDK_PLATFORM_VERSION := 5 NDK_SYSROOT=$(NDK_BASE)/platforms/android-$(NDK_PLATFORM_VERSION)/arch-arm NDK_UNAME := $(shell uname -s | tr '[A-Z]' '[a-z]') NDK_TOOLCHAIN_BASE=$(NDK_BASE)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/$(NDK_UNAME)-x86 CC := $(NDK_TOOLCHAIN_BASE)/bin/arm-linux-androideabi-gcc --sysroot=$(NDK_SYSROOT) OPT_CFLAGS = -O2 -funroll-loops -fomit-frame-pointer CFLAGS += LDFLAGS += -rdynamic -shared SHARED_LDFLAGS += -Wl,-soname,$(SHARED_LIB) -shared LIBS += -lc $(LIBS_android) STRIP := $(NDK_TOOLCHAIN_BASE)/bin/arm-linux-androideabi-strip \ --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m) endif ifeq ($(UNAME),Linux) CPU := $(shell uname -m) SOURCES += $(SOURCES_linux) EXTENSION = pd_linux SHARED_EXTENSION = so OS = linux PD_PATH = /usr OPT_CFLAGS = -O2 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += -fPIC ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags SHARED_LDFLAGS += -Wl,-soname,$(SHARED_LIB) -shared ALL_LIBS += -lc $(LIBS_linux) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m) endif ifeq ($(UNAME),GNU) # GNU/Hurd, should work like GNU/Linux for basically all externals CPU := $(shell uname -m) SOURCES += $(SOURCES_linux) EXTENSION = pd_linux SHARED_EXTENSION = so OS = linux PD_PATH = /usr OPT_CFLAGS = -O2 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += -fPIC ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB) ALL_LIBS += -lc $(LIBS_linux) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m) endif ifeq ($(UNAME),GNU/kFreeBSD) # Debian GNU/kFreeBSD, should work like GNU/Linux for basically all externals CPU := $(shell uname -m) SOURCES += $(SOURCES_linux) EXTENSION = pd_linux SHARED_EXTENSION = so OS = linux PD_PATH = /usr OPT_CFLAGS = -O2 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += -fPIC ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB) ALL_LIBS += -lc $(LIBS_linux) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m) endif ifeq (CYGWIN,$(findstring CYGWIN,$(UNAME))) CPU := $(shell uname -m) SOURCES += $(SOURCES_cygwin) EXTENSION = dll SHARED_EXTENSION = dll OS = cygwin PD_PATH = $(shell cygpath $$PROGRAMFILES)/pd OPT_CFLAGS = -O2 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += ALL_LDFLAGS += -rdynamic -shared -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB) -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" ALL_LIBS += -lc -lpd $(LIBS_cygwin) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS) endif ifeq (MINGW,$(findstring MINGW,$(UNAME))) CPU := $(shell uname -m) SOURCES += $(SOURCES_windows) EXTENSION = dll SHARED_EXTENSION = dll OS = windows PD_PATH = $(shell cd "$$PROGRAMFILES/pd" && pwd) # MinGW doesn't seem to include cc so force gcc CC=gcc OPT_CFLAGS = -O3 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += -mms-bitfields ALL_LDFLAGS += -s -shared -Wl,--enable-auto-import -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" -L"$(PD_PATH)/obj" SHARED_LDFLAGS += -shared -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" -L"$(PD_PATH)/obj" ALL_LIBS += -lpd -lwsock32 -lkernel32 -luser32 -lgdi32 $(LIBS_windows) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS) endif -include Makefile.local # in case somebody manually set the HELPPATCHES above HELPPATCHES ?= $(SOURCES:.c=-help.pd) $(PDOBJECTS:.pd=-help.pd) ALL_CFLAGS := $(CPPFLAGS) $(ALL_CFLAGS) $(OPT_CFLAGS) $(CFLAGS) ALL_LDFLAGS := $(ALL_LDFLAGS) $(LDFLAGS) ALL_LIBS := $(ALL_LIBS) $(LIBS) SHARED_SOURCES ?= $(shell test ! -e lib$(LIBRARY_NAME).c || \ echo lib$(LIBRARY_NAME).c ) SHARED_HEADERS ?= $(shell test ! -e $(LIBRARY_NAME).h || echo $(LIBRARY_NAME).h) SHARED_LIB ?= lib$(LIBRARY_NAME:=.$(SHARED_EXTENSION)) .PHONY = all clean distclean install dist \ etags dpkg-source showsetup \ libdir_install install-objects \ single_install install-libobject \ install-doc install-examples install-manual \ libdir $(LIBRARY_NAME) all: $(SOURCES:.c=.$(EXTENSION)) $(SHARED_LIB) %.o: %.c $(SHARED_HEADERS) $(CC) $(ALL_CFLAGS) -o $@ -c $< %.$(EXTENSION): %.o $(SHARED_LIB) $(CC) $(ALL_LDFLAGS) -o $@ $^ $(ALL_LIBS) chmod a-x $@ # this links everything into a single binary file $(LIBRARY_NAME): $(LIBRARY_NAME).$(EXTENSION) $(LIBRARY_NAME).$(EXTENSION): $(SOURCES:.c=.o) $(LIBRARY_NAME).o $(CC) $(ALL_LDFLAGS) -o $@ $^ $(ALL_LIBS) chmod a-x $@ $(SHARED_LIB): $(SHARED_SOURCES:.c=.o) $(CC) $(SHARED_LDFLAGS) $(LDFLAGS) -o $@ $^ $(ALL_LIBS) install: libdir_install # The meta and help files are explicitly installed to make sure they are # actually there. Those files are not optional, then need to be there. install-objects: $(SOURCES:.c=.$(EXTENSION)) $(SHARED_LIB) $(PDOBJECTS) $(SHARED_TCL_LIB) $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(INSTALL_DATA) $^ \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(wildcard $(SOURCES:.c=.tcl)))" || \ $(INSTALL_DATA) $(wildcard $(SOURCES:.c=.tcl)) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) libdir_install: install-objects install-doc install-examples install-manual # install library linked as single binary install-libobject: $(LIBRARY_NAME).$(EXTENSION) $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(INSTALL_PROGRAM) $^ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) -$(STRIP) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/$(LIBRARY_NAME).$(EXTENSION) single_install: install-libobject install-doc install-examples install-manual install-doc: $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(SOURCES) $(PDOBJECTS))" || \ $(INSTALL_DATA) $(HELPPATCHES) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(INSTALL_DATA) README.txt $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/README.txt $(INSTALL_DATA) LICENSE.txt $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/LICENSE.txt $(INSTALL_DATA) ChangeLog $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/CHANGES.txt install-examples: test -z "$(strip $(EXAMPLES))" || \ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples && \ for file in $(EXAMPLES); do \ $(INSTALL_DATA) examples/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples; \ done install-manual: test -z "$(strip $(MANUAL))" || \ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/manual && \ for file in $(MANUAL); do \ $(INSTALL_DATA) manual/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/manual; \ done clean: -rm -f -- $(SOURCES:.c=.o) $(SOURCES_LIB:.c=.o) $(SHARED_SOURCES:.c=.o) -rm -f -- $(SOURCES:.c=.$(EXTENSION)) -rm -f -- $(LIBRARY_NAME).o -rm -f -- $(LIBRARY_NAME).$(EXTENSION) -rm -f -- $(SHARED_LIB) distclean: clean -rm -f -- $(DISTBINDIR).tar.gz -rm -rf -- $(DISTBINDIR) -rm -f -- $(DISTDIR).tar.gz -rm -rf -- $(DISTDIR) -rm -f -- $(ORIGDIR).tar.gz -rm -rf -- $(ORIGDIR) $(DISTBINDIR): $(INSTALL_DIR) $(DISTBINDIR) libdir: all $(DISTBINDIR) $(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd $(DISTBINDIR) $(INSTALL_DATA) $(SOURCES) $(SHARED_SOURCES) $(SHARED_HEADERS) $(DISTBINDIR) $(INSTALL_DATA) $(HELPPATCHES) $(DISTBINDIR) test -z "$(strip $(EXTRA_DIST))" || \ $(INSTALL_DATA) $(EXTRA_DIST) $(DISTBINDIR) # tar --exclude-vcs -czpf $(DISTBINDIR).tar.gz $(DISTBINDIR) $(DISTDIR): $(INSTALL_DIR) $(DISTDIR) $(ORIGDIR): $(INSTALL_DIR) $(ORIGDIR) dist: $(DISTDIR) $(INSTALL_DATA) Makefile $(DISTDIR) $(INSTALL_DATA) README.txt $(DISTDIR) $(INSTALL_DATA) LICENSE.txt $(DISTDIR) $(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd $(DISTDIR) test -z "$(strip $(ALLSOURCES))" || \ $(INSTALL_DATA) $(ALLSOURCES) $(DISTDIR) test -z "$(strip $(wildcard $(ALLSOURCES:.c=.tcl)))" || \ $(INSTALL_DATA) $(wildcard $(ALLSOURCES:.c=.tcl)) $(DISTDIR) test -z "$(strip $(SHARED_HEADERS))" || \ $(INSTALL_DATA) $(SHARED_HEADERS) $(DISTDIR) test -z "$(strip $(SHARED_SOURCES))" || \ $(INSTALL_DATA) $(SHARED_SOURCES) $(DISTDIR) test -z "$(strip $(PDOBJECTS))" || \ $(INSTALL_DATA) $(PDOBJECTS) $(DISTDIR) test -z "$(strip $(HELPPATCHES))" || \ $(INSTALL_DATA) $(HELPPATCHES) $(DISTDIR) test -z "$(strip $(EXTRA_DIST))" || \ $(INSTALL_DATA) $(EXTRA_DIST) $(DISTDIR) test -z "$(strip $(EXAMPLES))" || \ $(INSTALL_DIR) $(DISTDIR)/examples && \ for file in $(EXAMPLES); do \ $(INSTALL_DATA) examples/$$file $(DISTDIR)/examples; \ done test -z "$(strip $(MANUAL))" || \ $(INSTALL_DIR) $(DISTDIR)/manual && \ for file in $(MANUAL); do \ $(INSTALL_DATA) manual/$$file $(DISTDIR)/manual; \ done tar --exclude-vcs -czpf $(DISTDIR).tar.gz $(DISTDIR) # make a Debian source package dpkg-source: debclean make distclean dist mv $(DISTDIR) $(ORIGDIR) tar --exclude-vcs -czpf ../$(ORIGDIR).orig.tar.gz $(ORIGDIR) rm -f -- $(DISTDIR).tar.gz rm -rf -- $(DISTDIR) $(ORIGDIR) cd .. && dpkg-source -b $(LIBRARY_NAME) etags: etags *.h $(SOURCES) ../../pd/src/*.[ch] /usr/include/*.h /usr/include/*/*.h showsetup: @echo "CC: $(CC)" @echo "CFLAGS: $(CFLAGS)" @echo "LDFLAGS: $(LDFLAGS)" @echo "LIBS: $(LIBS)" @echo "ALL_CFLAGS: $(ALL_CFLAGS)" @echo "ALL_LDFLAGS: $(ALL_LDFLAGS)" @echo "ALL_LIBS: $(ALL_LIBS)" @echo "PD_INCLUDE: $(PD_INCLUDE)" @echo "PD_PATH: $(PD_PATH)" @echo "objectsdir: $(objectsdir)" @echo "LIBRARY_NAME: $(LIBRARY_NAME)" @echo "LIBRARY_VERSION: $(LIBRARY_VERSION)" @echo "SOURCES: $(SOURCES)" @echo "SHARED_HEADERS: $(SHARED_HEADERS)" @echo "SHARED_SOURCES: $(SHARED_SOURCES)" @echo "SHARED_LIB: $(SHARED_LIB)" @echo "PDOBJECTS: $(PDOBJECTS)" @echo "ALLSOURCES: $(ALLSOURCES)" @echo "ALLSOURCES TCL: $(wildcard $(ALLSOURCES:.c=.tcl))" @echo "UNAME: $(UNAME)" @echo "CPU: $(CPU)" @echo "pkglibdir: $(pkglibdir)" @echo "DISTDIR: $(DISTDIR)" @echo "ORIGDIR: $(ORIGDIR)" pd-iemnet-0.2.1/NEWS000066400000000000000000000004621257237665700141210ustar00rootroot00000000000000what's new in iemnet? 0.1 - forked away from mrpeach/net - one thread for each socket - default-target concept: either send to all clients, a single client or all-but a single client - getting rid of cruft either not related to networking (e.g. file-handling) or workarounds for bugs/design problems pd-iemnet-0.2.1/NOTES.txt000066400000000000000000000021151257237665700150500ustar00rootroot00000000000000scratchpad for the development of iemnet ======================================== speed & syslocks ================ setting Pd's clocks is not thread-safe, but calling sys_lock() will slow the entire process down to unusability. therefore, we use a (per-receiver) thread, that get's waits on a pthread_cond_t and will syslock if needed. LATER there should only be one of these clock-threads (per RTE, in case we finally can run multiple Pd's in a single applications), that maintains it's own list of callbacks+data. tests for tcpclient/server: client disconnects -> server should get notified server disconnects -> client should get notified client crashes -> server should disconnect server crashes -> client should disconnect known BUGS: [tcpclient] now does all the actual connect/disconnect work in a helper-thread. unfortunately, iemnet__receiver_destroy() assumes that it is called from the main-thread and will outlet_list the remaining bytes in the dtor. however, outlet_list is not threadsafe. possible solution: see speed&syslocks for a leightweight thread-safe callback framework. pd-iemnet-0.2.1/README.txt000066400000000000000000000057041257237665700151240ustar00rootroot00000000000000iemnet - networking for Pd ========================== this is a fork of martin peach's "net" library, that allows low-level interaction with networks on OSI-layer 5 (transport layer). for a list of features, see FEATURES.txt Why fork? ========= the original library is still actively maintained by martin peach. however: - forking allows me to experiment with new features/techniques more easily - forking allows to remove all the legacy cruft (and not care about compatibility now) - the development mode in the original library would involve the upstream author "signing-off" any changes (debatable; but i don't want to submit experimental code to their stable code base) in practice one of the major drawbacks i see in upstream is, that (in the multithreaded objects), for each message a separate thread is spawned. this leads to excessive use of system ressources (detaching and joining threads takes time), easy DoS (each thread uses one in a limited number of thread handles), and abandons determinism (nobody guarantees that parallel threads are executed "in order"; thus a message in a later-spawned thread might be delivered to the socket earlier than older messages - effectively circumventing one of the promises of TCP/IP: that all packets will reappear in order; users have already reported this behaviour, which makes using those objects a bit unreliable) on the long run compatibility with the upstream library is intended. (though probably not for all the cruft that is in there) Design: ======= easy to maintain: re-used code is bundled in a small "library" (currently only a single file ienet.c), which is linked statically against the externals. this library handles all the send/receive stuff (whether it uses threads or not and if so how, is an implementation detail) the lib doesn't know anything about the actual transport protocol. it only interacts with a socket. easy to run: think speed, think reliability all known implementations for pd are either slow or will freeze Pd when under _heavy_ load. most do both. iemnet wants to provide objects whih allow you to saturate the network connection and still keep Pd reactive. (sidenote: saturating even a 100MBit network with Pd might lead to audio dropouts; this is not necessarily related to the network but rather to the amount of data processed by Pd...) easy to use: probably not; but at least it has the same (basic) API as mrpeach/net so a switch should be easy. "basic" means "not everything", so messages for special workarounds in mrpeach/net (e.g. the block/unblock stuff) are not supported, as well as debugging features ("dump") and features not related to networking (e.g. the ability to read a file from harddisk) Authors: ======== currently iemnet is developed by IOhannes m zmölnig it (being a fork) is heavily based on code written by Martin Peach, who again has used code by Olaf Matthes and Miller Puckette LICENSE: ======== iemnet is published under the GPL. see LICENSE.txt for more information pd-iemnet-0.2.1/astyle.rc000066400000000000000000000005261257237665700152520ustar00rootroot00000000000000## asytyle configuration for iemnet # usage: astyle --options=astyle.rc *.c *.h ## CRLF line-ending lineend=linux ## make sure that code fits on an old-school terminal max-code-length=75 # maximum indentation on continuation lines max-instatement-indent=40 ## "One True Brace Style" style=1tbs ## hardly an indentation indent=spaces=2 pd-iemnet-0.2.1/build/000077500000000000000000000000001257237665700145175ustar00rootroot00000000000000pd-iemnet-0.2.1/build/autotests/000077500000000000000000000000001257237665700165525ustar00rootroot00000000000000pd-iemnet-0.2.1/build/autotests/Makefile.am000066400000000000000000000010141257237665700206020ustar00rootroot00000000000000AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 SUBDIRS=tests AM_CPPFLAGS = -I$(top_srcdir) lib_LTLIBRARIES = libiemnet.la libiemnet_la_LDFLAGS = -version-info 1 -no-undefined libiemnet_la_CFLAGS = #libiemnet_la_CFLAGS += -fvisibility=hidden libiemnet_la_LIBADD = $(LIBM) libiemnet_la_SOURCES = \ $(top_srcdir)/../../iemnet_data.c \ $(top_srcdir)/../../iemnet_data.h \ $(top_srcdir)/../../iemnet_receiver.c \ $(top_srcdir)/../../iemnet_sender.c \ $(top_srcdir)/../../iemnet.c \ $(top_srcdir)/../../iemnet.h pd-iemnet-0.2.1/build/autotests/README.txt000066400000000000000000000003211257237665700202440ustar00rootroot00000000000000autotools for iemnet ==================== currently, iemnet does NOT require autotools to build. what you find in here is mainly to run some automated tests, so the only useful build-target is: $ make check pd-iemnet-0.2.1/build/autotests/configure.ac000066400000000000000000000006101257237665700210350ustar00rootroot00000000000000AC_INIT([iemnet],[0.0.1],[zmoelnig@iem.at], [iemnet],[http://ambisonics.iem.at/xchange/format]) AM_INIT_AUTOMAKE AM_PROG_LIBTOOL AC_CONFIG_SRCDIR([../../iemnet.h]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_FILES([Makefile tests/Makefile]) AC_PROG_INSTALL AC_LANG_C AC_PROG_CC AC_PROG_MAKE_SET AC_HEADER_STDC /* check for math */ AC_CHECK_LIB([m],[sqrt]) AX_PTHREAD AC_OUTPUT pd-iemnet-0.2.1/build/autotests/m4/000077500000000000000000000000001257237665700170725ustar00rootroot00000000000000pd-iemnet-0.2.1/build/autotests/m4/ax_pthread.m4000066400000000000000000000261041257237665700214560ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_pthread.html # =========================================================================== # # SYNOPSIS # # AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) # # DESCRIPTION # # This macro figures out how to build C programs using POSIX threads. It # sets the PTHREAD_LIBS output variable to the threads library and linker # flags, and the PTHREAD_CFLAGS output variable to any special C compiler # flags that are needed. (The user can also force certain compiler # flags/libs to be tested by setting these environment variables.) # # Also sets PTHREAD_CC to any special C compiler that is needed for # multi-threaded programs (defaults to the value of CC otherwise). (This # is necessary on AIX to use the special cc_r compiler alias.) # # NOTE: You are assumed to not only compile your program with these flags, # but also link it with them as well. e.g. you should link with # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS # # If you are only building threads programs, you may wish to use these # variables in your default LIBS, CFLAGS, and CC: # # LIBS="$PTHREAD_LIBS $LIBS" # CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # CC="$PTHREAD_CC" # # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant # has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name # (e.g. PTHREAD_CREATE_UNDETACHED on AIX). # # ACTION-IF-FOUND is a list of shell commands to run if a threads library # is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it # is not found. If ACTION-IF-FOUND is not specified, the default action # will define HAVE_PTHREADS. # # Please let the authors know if this macro fails on any platform, or if # you have any other suggestions or comments. This macro was based on work # by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help # from M. Frigo), as well as ac_pthread and hb_pthread macros posted by # Alejandro Forero Cuervo to the autoconf macro repository. We are also # grateful for the helpful feedback of numerous users. # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 7 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) AC_DEFUN([AX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_SAVE AC_LANG_C ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes) AC_MSG_RESULT($ax_pthread_ok) if test x"$ax_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" ;; *-darwin*) acx_pthread_flags="-pthread $acx_pthread_flags" ;; esac if test x"$ax_pthread_ok" = xno; then for flag in $ax_pthread_flags; do case $flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -*) AC_MSG_CHECKING([whether pthreads work with $flag]) PTHREAD_CFLAGS="$flag" ;; pthread-config) AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no) if test x"$ax_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) AC_MSG_CHECKING([for the pthreads library -l$flag]) PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_TRY_LINK([#include static void routine(void* a) {a=0;} static void* start_routine(void* a) {return a;}], [pthread_t th; pthread_attr_t attr; pthread_join(th, 0); pthread_attr_init(&attr); pthread_cleanup_push(routine, 0); pthread_create(&th,0,start_routine,0); pthread_cleanup_pop(0); ], [ax_pthread_ok=yes]) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" AC_MSG_RESULT($ax_pthread_ok) if test "x$ax_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$ax_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. AC_MSG_CHECKING([for joinable pthread attribute]) attr_name=unknown for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do AC_TRY_LINK([#include ], [int attr=$attr; return attr;], [attr_name=$attr; break]) done AC_MSG_RESULT($attr_name) if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, [Define to necessary symbol if this constant uses a non-standard name on your system.]) fi AC_MSG_CHECKING([if more special flags are required for pthreads]) flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; esac AC_MSG_RESULT(${flag}) if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with xlc_r or cc_r if test x"$GCC" != xyes; then AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC}) else PTHREAD_CC=$CC fi else PTHREAD_CC="$CC" fi AC_SUBST(PTHREAD_LIBS) AC_SUBST(PTHREAD_CFLAGS) AC_SUBST(PTHREAD_CC) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$ax_pthread_ok" = xyes; then ifelse([$1],,AC_DEFINE(HAVE_PTHREADS,1,[Define if you have POSIX threads libraries and header files.]),[$1]) : else ax_pthread_ok=no $2 fi AC_LANG_RESTORE ])dnl AX_PTHREAD pd-iemnet-0.2.1/build/autotests/tests/000077500000000000000000000000001257237665700177145ustar00rootroot00000000000000pd-iemnet-0.2.1/build/autotests/tests/Makefile.am000066400000000000000000000012031257237665700217440ustar00rootroot00000000000000AUTOMAKE_OPTIONS = foreign AM_LDFLAGS= -module -avoid-version -shared -shrext .pd_linux TEST_EXTENSIONS = .la LA_LOG_COMPILER = $(srcdir)/runtest.sh AM_CPPFLAGS=-I$(top_srcdir)/../.. AM_LDFLAGS+=$(top_builddir)/libiemnet.la -rpath /tmp SOURCES=common.h noinst_HEADERS=common.h EXTRA_DIST=runtest.sh TESTS = \ pass.la skip.la fail.la \ serialqueue.la threadedqueue.la XFAIL_TESTS = fail.la check_LTLIBRARIES= \ pass.la skip.la fail.la \ serialqueue.la threadedqueue.la pass_la_SOURCES=pass.c skip_la_SOURCES=skip.c fail_la_SOURCES=fail.c threadedqueue_la_SOURCES=threadedqueue.c serialqueue_la_SOURCES=serialqueue.c pd-iemnet-0.2.1/build/autotests/tests/common.h000066400000000000000000000023241257237665700213560ustar00rootroot00000000000000#ifndef TESTS_COMMON_H #define TESTS_COMMON_H #include "iemnet.h" #include static inline void pass(void) {exit(0); } static inline void fail(void) {exit(1); } static inline void skip(void) {exit(77); } #include #include static inline void pass_if (int test, int line, const char *format, ...) { if (test) { va_list argptr ; printf("@%d: ", line); va_start (argptr, format) ; vprintf (format, argptr) ; va_end (argptr) ; printf("\n"); pass(); } ; } /* pass_if */ static inline void skip_if (int test, int line, const char *format, ...) { if (test) { va_list argptr ; printf("@%d: ", line); va_start (argptr, format) ; vprintf (format, argptr) ; va_end (argptr) ; printf("\n"); skip(); } ; } /* skip_if */ static inline void fail_if (int test, int line, const char *format, ...) { if (test) { va_list argptr ; printf("@%d: ", line); va_start (argptr, format) ; vprintf (format, argptr) ; va_end (argptr) ; printf("\n"); fail(); } ; } /* fail_if */ #define STRINGIFY(x) #x #define STARTTEST(x) printf("============ %s[%04d]:\t%s '%s'\n", __FILE__, __LINE__, __FUNCTION__, x) #endif /* TESTS_COMMON_H */ pd-iemnet-0.2.1/build/autotests/tests/fail.c000066400000000000000000000000651257237665700207740ustar00rootroot00000000000000#include "common.h" void fail_setup() { fail(); } pd-iemnet-0.2.1/build/autotests/tests/pass.c000066400000000000000000000000731257237665700210260ustar00rootroot00000000000000#include "common.h" void pass_setup(void) { pass(); } pd-iemnet-0.2.1/build/autotests/tests/runtest.sh000077500000000000000000000014011257237665700217530ustar00rootroot00000000000000#!/bin/sh EXTERNAL=$1 EXTERNAL=${EXTERNAL%.la} EXTERNAL=${EXTERNAL#./} TESTTYPE=$2 ################################## PD=pd PDARGS="-nrt -nogui -path .libs" PDARGS="-noprefs -nostdpath -nosound -nrt -nogui -path .libs" #PDARGS="-nostdpath -nosound -nrt -nogui -path .libs" #VALGRIND=valgrind VALGRIND="valgrind --error-exitcode=1" do_runtest() { case "$1" in mem*|MEM*) ${VALGRIND} ${PD} ${PDARGS} -lib ${EXTERNAL} ;; DRD|drd) ${VALGRIND} --tool=drd ${PD} ${PDARGS} -lib ${EXTERNAL} ;; HEL*|hel*) ${VALGRIND} --tool=helgrind ${PD} ${PDARGS} -lib ${EXTERNAL} ;; *) ${PD} ${PDARGS} -lib ${EXTERNAL} ;; esac } #do_runtest #do_runtest MEM #do_runtest DRD #do_runtest HEL #do_runtest && do_runtest MEM && do_runtest DRD do_runtest $TESTTYPE pd-iemnet-0.2.1/build/autotests/tests/serialqueue.c000066400000000000000000000022521257237665700224050ustar00rootroot00000000000000#include #include #define NUMCHUNKS 1000 typedef union { unsigned char cp; int count; } data_t; static int producer(t_iemnet_queue*q, unsigned int count, unsigned int msec) { unsigned int i; data_t data; for(i=0; isize) { error("size mismatch %d!=%d", sizeof(data_t), chunk->size); fail(); } data=chunk->data; // post("consumed %d", data->count); iemnet__chunk_destroy(chunk); } printf("\n"); return 0; } void serialqueue_setup(void) { t_iemnet_queue*q=queue_create(); producer(q, 1000, 1); consumer(q); queue_destroy(q); pass(); } pd-iemnet-0.2.1/build/autotests/tests/skip.c000066400000000000000000000000711257237665700210240ustar00rootroot00000000000000#include "common.h" void skip_setup(void) { skip(); } pd-iemnet-0.2.1/build/autotests/tests/threadedqueue.c000066400000000000000000000030511257237665700227040ustar00rootroot00000000000000#include #include #define NUMCHUNKS 1000 typedef union { unsigned char cp; int count; } data_t; static int producer(t_iemnet_queue*q, unsigned int count, unsigned int msec) { unsigned int i; data_t data; for(i=0; isize) { error("size mismatch %d!=%d", sizeof(data_t), chunk->size); fail(); } data=chunk->data; //printf("%d ", data->count); iemnet__chunk_destroy(chunk); } printf("\n"); return 0; } static void* consumer_thread(void*qq) { t_iemnet_queue*q=(t_iemnet_queue*)qq; consumer(q); return NULL; } void threadedqueue_setup(void) { pthread_t thread; pthread_attr_t threadattr; t_iemnet_queue*q=queue_create(); /* prepare child thread */ if(pthread_attr_init(&threadattr) < 0) { error("warning: could not prepare child thread"); fail(); } if(pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED) < 0) { error("warning: could not prepare child thread..."); fail(); } if(pthread_create(&thread, &threadattr, consumer_thread, q) < 0) { error("warning: could not create child thread"); fail(); } producer(q, 1000, 1); queue_destroy(q); pass(); } pd-iemnet-0.2.1/build/coverity/000077500000000000000000000000001257237665700163635ustar00rootroot00000000000000pd-iemnet-0.2.1/build/coverity/coverity_branch.sh000077500000000000000000000012001257237665700220740ustar00rootroot00000000000000#!/bin/sh ## merges master into coverity_scan and pushes to 'origin' PUSH= if [ "x$1" = "x-n" ]; then PUSH=no fi if [ "x$1" = "x-y" ]; then PUSH=yes fi if git push . master:coverity_scan then if [ "x${PUSH}" = "x" ]; then echo -n "Shall I push 'coverity_scan' to remote [Y/n]? " 1>&2 read PUSH if [ "x${PUSH}" = "x" ]; then PUSH=yes fi case "${PUSH}" in yes|YES|y|Y) PUSH=yes ;; no|NO|n|N) PUSH=no ;; *) echo "Invalid value '${PUSH}' - assuming 'no'" 1>&2 PUSH=no ;; esac fi if [ "x${PUSH}" = "xyes" ]; then git push origin coverity_scan:coverity_scan fi fi pd-iemnet-0.2.1/build/coverity/coverity_model.c000066400000000000000000000014031257237665700215510ustar00rootroot00000000000000/* Coverity Scan model * * This is a modeling file for Coverity Scan. Modeling helps to avoid false * positives. * * - A model file can't import any header files. * - Therefore only some built-in primitives like int, char and void are * available but not wchar_t, NULL etc. * - Modeling doesn't need full structs and typedefs. Rudimentary structs * and similar types are sufficient. * - An uninitialized local pointer is not an error. It signifies that the * variable could be either NULL or have some data. * * Coverity Scan doesn't pick up modifications automatically. The model file * must be uploaded by an admin in the analysis settings of * http://scan.coverity.com/projects/1830 */ void sys_closesocket(int fd) { __coverity_close__(fd); } pd-iemnet-0.2.1/build/w32-vs2003/000077500000000000000000000000001257237665700160655ustar00rootroot00000000000000pd-iemnet-0.2.1/build/w32-vs2003/iemnet.sln000066400000000000000000000013461257237665700200700ustar00rootroot00000000000000Microsoft Visual Studio Solution File, Format Version 8.00 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "iemnet", "iemnet.vcproj", "{6B55773B-3FF5-4F09-B538-2A7007DEC4DB}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject Global GlobalSection(SolutionConfiguration) = preSolution Release = Release EndGlobalSection GlobalSection(ProjectConfiguration) = postSolution {6B55773B-3FF5-4F09-B538-2A7007DEC4DB}.Release.ActiveCfg = Release|Win32 {6B55773B-3FF5-4F09-B538-2A7007DEC4DB}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection GlobalSection(ExtensibilityAddIns) = postSolution EndGlobalSection EndGlobal pd-iemnet-0.2.1/build/w32-vs2003/iemnet.vcproj000066400000000000000000000063751257237665700206060ustar00rootroot00000000000000 pd-iemnet-0.2.1/build/w32-vs2008/000077500000000000000000000000001257237665700160725ustar00rootroot00000000000000pd-iemnet-0.2.1/build/w32-vs2008/iemnet.sln000066400000000000000000000012611257237665700200710ustar00rootroot00000000000000Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "iemnet", "iemnet.vcproj", "{6B55773B-3FF5-4F09-B538-2A7007DEC4DB}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {6B55773B-3FF5-4F09-B538-2A7007DEC4DB}.Release|Win32.ActiveCfg = Release|Win32 {6B55773B-3FF5-4F09-B538-2A7007DEC4DB}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal pd-iemnet-0.2.1/build/w32-vs2008/iemnet.vcproj000066400000000000000000000072341257237665700206060ustar00rootroot00000000000000 pd-iemnet-0.2.1/iemnet-meta.pd000066400000000000000000000007021257237665700161510ustar00rootroot00000000000000#N canvas 169 49 432 242 10; #X text 47 84 iemnet: high performance networking with Pd; #X text 41 134 (c) 2010 IOhannes m zmölnig \, Institute of Electronic Music and Acoustics (IEM) \, University of Music and Performing Arts \, Graz \, Austria; #N canvas 25 49 420 300 META 0; #X text 10 10 VERSION 0.2.1; #X text 10 30 AUTHOR IOhannes m zmoelnig ; #X text 10 50 NAME iemnet; #X text 10 70 LICENSE GPL-2; #X restore 20 20 pd META; pd-iemnet-0.2.1/iemnet.c000066400000000000000000000147031257237665700150520ustar00rootroot00000000000000/* iemnet * this file provides core infrastructure for the iemnet-objects * * copyright © 2010-2015 IOhannes m zmölnig, IEM */ /* This program is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation; either version 2 */ /* of the License, or (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, see */ /* http://www.gnu.org/licenses/ */ /* */ #define DEBUGLEVEL #include "iemnet.h" #include #include /* close a socket properly */ void iemnet__closesocket(int sockfd, int verbose) { if(sockfd >=0) { #ifndef SHUT_RDWR # define SHUT_RDWR 2 #endif int how=SHUT_RDWR; int err = shutdown(sockfd, how); /* needed on linux, since the recv won't shutdown on sys_closesocket() alone */ if(verbose && err) { perror("iemnet:socket-shutdown"); } sys_closesocket(sockfd); } } /* various functions to send data to output in a uniform way */ void iemnet__addrout(t_outlet*status_outlet, t_outlet*address_outlet, long address, unsigned short port) { static t_atom addr[5]; static int firsttime=1; if(firsttime) { int i=0; for(i=0; i<5; i++) { SETFLOAT(addr+i, 0); } firsttime=0; } addr[0].a_w.w_float = (address & 0xFF000000)>>24; addr[1].a_w.w_float = (address & 0x0FF0000)>>16; addr[2].a_w.w_float = (address & 0x0FF00)>>8; addr[3].a_w.w_float = (address & 0x0FF); addr[4].a_w.w_float = port; if(status_outlet ) { outlet_anything(status_outlet , gensym("address"), 5, addr); } if(address_outlet) { outlet_list (address_outlet, gensym("list" ), 5, addr); } } void iemnet__numconnout(t_outlet*status_outlet, t_outlet*numcon_outlet, int numconnections) { t_atom atom[1]; SETFLOAT(atom, numconnections); if(status_outlet) { outlet_anything(status_outlet , gensym("connections"), 1, atom); } if(numcon_outlet) { outlet_float (numcon_outlet, numconnections); } } void iemnet__socketout(t_outlet*status_outlet, t_outlet*socket_outlet, int socketfd) { t_atom atom[1]; SETFLOAT(atom, socketfd); if(status_outlet) { outlet_anything(status_outlet , gensym("socket"), 1, atom); } if(socket_outlet) { outlet_float (socket_outlet, socketfd); } } void iemnet__streamout(t_outlet*outlet, int argc, t_atom*argv, int stream) { if(NULL==outlet) { return; } if(stream) { while(argc-->0) { outlet_list(outlet, gensym("list"), 1, argv); argv++; } } else { outlet_list(outlet, gensym("list"), argc, argv); } } typedef struct _names { t_symbol*name; struct _names*next; } t_iemnet_names; static t_iemnet_names*namelist=0; static int iemnet__nametaken(const char*namestring) { t_symbol*name=gensym(namestring); t_iemnet_names*curname=namelist; t_iemnet_names*lastname=curname; while(curname) { if(name==(curname->name)) { return 1; } lastname=curname; curname=curname->next; } // new name! curname=(t_iemnet_names*)malloc(sizeof(t_iemnet_names)); curname->name=name; curname->next=0; if(lastname) { lastname->next=curname; } else { namelist=curname; } return 0; } #ifndef BUILD_DATE # define BUILD_DATE "on " __DATE__ " at " __TIME__ #endif int iemnet__register(const char*name) { if(iemnet__nametaken(name)) { return 0; } post("iemnet - networking with Pd: [%s]", name); #ifdef VERSION post(" version "VERSION""); #endif post(" compiled "BUILD_DATE""); post(" copyright © 2010-2015 IOhannes m zmoelnig, IEM"); post(" based on mrpeach/net, based on maxlib"); return 1; } #ifdef _MSC_VER void tcpclient_setup(void); void tcpreceive_setup(void); void tcpsend_setup(void); void tcpserver_setup(void); void udpclient_setup(void); void udpreceive_setup(void); void udpsend_setup(void); void udpserver_setup(void); #endif static int iemnet_debuglevel_=0; static pthread_mutex_t debug_mtx = PTHREAD_MUTEX_INITIALIZER; void iemnet_debuglevel(void*x, t_float f) { static int firsttime=1; #ifdef IEMNET_HAVE_DEBUG int debuglevel=(int)f; pthread_mutex_lock(&debug_mtx); iemnet_debuglevel_=debuglevel; pthread_mutex_unlock(&debug_mtx); post("iemnet: setting debuglevel to %d", debuglevel); #else if(firsttime) { error("iemnet compiled without debug!"); } #endif firsttime=0; } int iemnet_debug(int debuglevel, const char*file, unsigned int line, const char*function) { #ifdef IEMNET_HAVE_DEBUG int debuglevel_=0; pthread_mutex_lock(&debug_mtx); debuglevel_=iemnet_debuglevel_; pthread_mutex_unlock(&debug_mtx); if(debuglevel_ & debuglevel) { startpost("[%s[%d]:%s#%d] ", file, line, function, debuglevel); return 1; } #endif return 0; } IEMNET_EXTERN void iemnet_setup(void) { #ifdef _MSC_VER tcpclient_setup(); tcpreceive_setup(); tcpsend_setup(); tcpserver_setup(); udpclient_setup(); udpreceive_setup(); udpsend_setup(); udpserver_setup(); #endif } #include #include #include void iemnet_log(const void *object, const t_iemnet_loglevel level, const char *fmt, ...) { t_pd*x=(t_pd*)object; const char*name=(x && (*x) && ((*x)->c_name))?((*x)->c_name->s_name):"iemnet"; char buf[MAXPDSTRING]; va_list ap; t_int arg[8]; va_start(ap, fmt); vsnprintf(buf, MAXPDSTRING-1, fmt, ap); va_end(ap); strcat(buf, "\0"); #if (defined PD_MINOR_VERSION) && (PD_MINOR_VERSION >= 43) logpost(x, level, "[%s]: %s", name, buf); #else if(level>1) { post("[%s]: %s", name, buf); } else { pd_error(x, "[%s]: %s", name, buf); } #endif } pd-iemnet-0.2.1/iemnet.h000066400000000000000000000236151257237665700150610ustar00rootroot00000000000000/* *********************************************+ * iemnet * networking for Pd * * (c) 2010 IOhannes m zmölnig * Institute of Electronic Music and Acoustics (IEM) * University of Music and Dramatic Arts (KUG), Graz, Austria * * based on net/ library by Martin Peach * based on maxlib by Olaf Matthes */ /* ---------------------------------------------------------------------------- */ /* This program is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation; either version 2 */ /* of the License, or (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, see */ /* http://www.gnu.org/licenses/ */ /* */ /* ---------------------------------------------------------------------------- */ #ifndef INCLUDE_IEMNET_H_ #define INCLUDE_IEMNET_H_ #include "m_pd.h" /* from s_stuff.h */ typedef void (*t_fdpollfn)(void *ptr, int fd); EXTERN void sys_closesocket(int fd); EXTERN void sys_sockerror(char *s); EXTERN void sys_addpollfn(int fd, t_fdpollfn fn, void *ptr); EXTERN void sys_rmpollfn(int fd); #ifdef _WIN32 # include # include #else # include # include # include #endif #include /* iemnet_data.c */ #include "iemnet_data.h" /* iemnet_sender.c */ /** * opaque data type used for sending data over a socket */ typedef struct _iemnet_sender t_iemnet_sender; EXTERN_STRUCT _iemnet_sender; /** * user provided send function * (defaults to just using send) * this function is guaranteed to be called with a valid 'chunk', * and the 'userdata' and 'sockfd' provided at sender-creation */ typedef int (*t_iemnet_sendfunction)(const void*userdata, int sockfd, t_iemnet_chunk*chunk); /** * create a sender to a given socket * * \param sock a previously opened socket * \param sendfun a send()-implementation (or NULL, to use the default send/sendto based implementation) * \param userdata pointer to optional userdata to be passsed to `sendfun` * \param bool indicating whether this function is called from a subthread (1) or the mainthread (0) * \return pointer to a sender object * \note the socket must be writeable */ t_iemnet_sender*iemnet__sender_create(int sock, t_iemnet_sendfunction sendfun, const void*userdata, int); /** * destroy a sender to a given socket * destroying a sender will free all resources of the sender * * \param pointer to a sender object to be destroyed * \param bool indicating whether this function is called from a subthread (1) or the mainthread (0) * * \note it will also close() the socket */ void iemnet__sender_destroy(t_iemnet_sender*, int); /** * send data over a socket * * \param pointer to a sender object * \param pointer to a chunk of data to be sent * \return the current fill state of the send buffer * * \note the sender creates a local copy of chunk; the caller has to delete their own copy */ int iemnet__sender_send(t_iemnet_sender*, t_iemnet_chunk*); /** * query the fill state of the send buffer * * \param pointer to a sender object * \return the current fill state of the send buffer */ int iemnet__sender_getsize(t_iemnet_sender*); /* iemnet_receiver.c */ /** * opaque data type used for receiving data from a socket */ typedef struct _iemnet_receiver t_iemnet_receiver; EXTERN_STRUCT _iemnet_receiver; /** * callback function for receiving * whenever data arrives at the socket, a callback will be called synchronously * if rawdata is NULL, this signifies that the socket has been closed */ typedef void (*t_iemnet_receivecallback)(void*userdata , t_iemnet_chunk*rawdata ); /** * create a receiver object * * whenever something is received on the socket, the callback is called with the payload in the main thread of the caller * * \param sock the (readable) socket to receive from * \param data user data to be passed to callback * \param callback a callback function that is called on the caller's side * \param subthread bool indicating whether this function is called from a subthread (1) or the mainthread (0) * * \note the callback will be scheduled in the caller's thread with clock_delay() */ t_iemnet_receiver*iemnet__receiver_create(int sock, void*data, t_iemnet_receivecallback callback, int subthread); /** * destroy a receiver at a given socket * destroying a receiver will free all resources of the receiver * * \param pointer to a receiver object to be destroyed * \param bool indicating whether this function is called from a subthread (1) or the mainthread (0) * * \note it will also close() the socket */ void iemnet__receiver_destroy(t_iemnet_receiver*, int subthread); /** * query the fill state of the receive buffer * * \param pointer to a receiver object * \return the current fill state of the receive buffer */ int iemnet__receiver_getsize(t_iemnet_receiver*); /* convenience functions */ /** * properly close a socket fd * * \param sock socket to close */ void iemnet__closesocket(int fd, int verbose); /** * output the address (IP, port) * the given address is first output through the status_outlet as a "host" message * and then as a list through the address_outlet * * \param status_outlet outlet for general status messages * \param address_outlet outlet for addresses only * \param address the host ip * \param port the host port * * \note the address will be output as a 5 element list, with the 1st 4 elements denoting the quads of the IP address (as bytes) and the last element the port */ void iemnet__addrout(t_outlet*status_outlet, t_outlet*address_outlet, long address, unsigned short port); /** * output the socket we received data from * the given socket is first output through the status_outlet as a "socket" message * and then as a single number through the socket_outlet * * \param status_outlet outlet for general status messages * \param socket_outlet outlet for sockets only * \param sockfd the socket */ void iemnet__socketout(t_outlet*status_outlet, t_outlet*socket_outlet, int sockfd); /** * output the number of connections * the given number of connections is first output through the status_outlet as a "connections" message * and then as a single number through the numconn_outlet * * \param status_outlet outlet for general status messages * \param address_outlet outlet for numconnections only * \param numconnections the number of connections */ void iemnet__numconnout(t_outlet*status_outlet, t_outlet*numconn_outlet, int numconnections); /** * output a list as a stream (serialize) * * the given list of atoms will be sent to the output one-by-one * * \param outlet outlet to sent the data to * \param argc size of the list * \param argv data * \param stream if true, serialize the data; if false output as "packets" * * \note with stream based protocols (TCP/IP) the length of the received lists has no meaning, so the data has to be serialized anyhow; however when creating proxies, sending serialized data is often slow, so there is an option to disable serialization */ void iemnet__streamout(t_outlet*outlet, int argc, t_atom*argv, int stream); /** * register an objectname and printout a banner * * this will printout a copyright notice * additionally, it will return whether it has already been called for the given name * * \param name an objectname to "register" * \return 1 if this function has been called the first time with the given name, 0 otherwise * */ int iemnet__register(const char*name); #if defined(_MSC_VER) # define snprintf _snprintf # define IEMNET_EXTERN __declspec(dllexport) extern # define CCALL __cdecl # define IEMNET_INITIALIZER(f) \ static void autoinit__ ## f(void) { f(); } #elif defined(__GNUC__) # define IEMNET_EXTERN extern # define CCALL # define IEMNET_INITIALIZER(f) \ static void autoinit__ ## f(void) __attribute__((constructor)); \ static void autoinit__ ## f(void) { f(); } #endif typedef enum { IEMNET_FATAL = 0, IEMNET_ERROR = 1, IEMNET_NORMAL = 2, IEMNET_VERBOSE = 3, IEMNET_DEBUG = 4 } t_iemnet_loglevel; void iemnet_log(const void *object, const t_iemnet_loglevel level, const char *fmt, ...); /** * \fn void DEBUG(const char* format,...); * * \brief debug output * \note this will only take effect if DEBUG is not undefined */ #ifdef IEMNET_HAVE_DEBUG # undef IEMNET_HAVE_DEBUG #endif #ifdef DEBUG # define IEMNET_HAVE_DEBUG 1 #endif void iemnet_debuglevel(void*,t_float); int iemnet_debug(int debuglevel, const char*file, unsigned int line, const char*function); #define DEBUGMETHOD(c) class_addmethod(c, (t_method)iemnet_debuglevel, gensym("debug"), A_FLOAT, 0) #ifdef DEBUG # undef DEBUG # define DEBUG if(iemnet_debug(DEBUGLEVEL, __FILE__, __LINE__, __FUNCTION__))post #else static void debug_dummy(const char *format, ...) { ; } # define DEBUG debug_dummy #endif #define MARK() post("%s:%d [%s]", __FILE__, __LINE__, __FUNCTION__) #endif /* INCLUDE_IEMNET_H_ */ pd-iemnet-0.2.1/iemnet_data.c000066400000000000000000000253551257237665700160500ustar00rootroot00000000000000/* iemnet * * data handling code * - wrappers for data "chunks" * - queues * * copyright © 2010-2015 IOhannes m zmölnig, IEM */ /* This program is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation; either version 2 */ /* of the License, or (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, see */ /* http://www.gnu.org/licenses/ */ /* */ #define DEBUGLEVEL 8 #include "iemnet.h" #include "iemnet_data.h" #include #include #include #include #include #define INBUFSIZE 65536L /* was 4096: size of receiving data buffer */ /* data handling */ t_iemnet_floatlist*iemnet__floatlist_init(t_iemnet_floatlist*cl) { unsigned int i; if(NULL==cl) { return NULL; } for(i=0; isize; i++) { SETFLOAT((cl->argv+i), 0.f); } return cl; } void iemnet__floatlist_destroy(t_iemnet_floatlist*cl) { if(NULL==cl) { return; } if(cl->argv) { free(cl->argv); } cl->argv=NULL; cl->argc=0; cl->size=0; free(cl); } t_iemnet_floatlist*iemnet__floatlist_create(unsigned int size) { t_iemnet_floatlist*result=(t_iemnet_floatlist*)malloc(sizeof( t_iemnet_floatlist)); if(NULL==result) { return NULL; } result->argv = (t_atom*)malloc(size*sizeof(t_atom)); if(NULL==result->argv) { iemnet__floatlist_destroy(result); return NULL; } result->argc=size; result->size=size; result=iemnet__floatlist_init(result); return result; } t_iemnet_floatlist*iemnet__floatlist_resize(t_iemnet_floatlist*cl, unsigned int size) { t_atom*tmp; if (NULL==cl) { return iemnet__floatlist_create(size); } if(size<=cl->size) { cl->argc=size; return cl; } tmp=(t_atom*)malloc(size*sizeof(t_atom)); if(NULL==tmp) { return NULL; } free(cl->argv); cl->argv=tmp; cl->argc=cl->size=size; cl=iemnet__floatlist_init(cl); return cl; } void iemnet__chunk_destroy(t_iemnet_chunk*c) { if(NULL==c) { return; } if(c->data) { free(c->data); } c->data=NULL; c->size=0; free(c); } void iemnet__chunk_print(t_iemnet_chunk*c) { unsigned int i=0; startpost("chunk[%p:%d]", c, c?c->size:0); if(!c) { return; } for(i=0; isize; i++) { startpost(" %d", c->data[i]); } endpost(); } t_iemnet_chunk* iemnet__chunk_create_empty(int size) { t_iemnet_chunk*result=NULL; if(size<1) { return NULL; } result=(t_iemnet_chunk*)malloc(sizeof(t_iemnet_chunk)); if(result) { result->size=size; result->data=(unsigned char*)malloc(sizeof(unsigned char)*size); if(NULL == result->data) { result->size=0; iemnet__chunk_destroy(result); return NULL; } memset(result->data, 0, result->size); result->addr=0L; result->port=0; result->family=AF_INET; } return result; } t_iemnet_chunk* iemnet__chunk_create_data(int size, unsigned char*data) { t_iemnet_chunk*result=iemnet__chunk_create_empty(size); if(result) { memcpy(result->data, data, result->size); } return result; } t_iemnet_chunk* iemnet__chunk_create_dataaddr(int size, unsigned char*data, struct sockaddr_in*addr) { t_iemnet_chunk*result=iemnet__chunk_create_data(size, data); if(result && addr) { result->addr = ntohl(addr->sin_addr.s_addr); result->port = ntohs(addr->sin_port); result->family = addr->sin_family; } return result; } t_iemnet_chunk* iemnet__chunk_create_list(int argc, t_atom*argv) { int i; t_iemnet_chunk*result=iemnet__chunk_create_empty(argc); if(NULL==result) { return NULL; } for(i=0; idata[i]=c; argv++; } return result; } t_iemnet_chunk*iemnet__chunk_create_chunk(t_iemnet_chunk*c) { t_iemnet_chunk*result=NULL; if(NULL==c) { return NULL; } result=iemnet__chunk_create_data(c->size, c->data); if(result) { result->addr=c->addr; result->port=c->port; } return result; } t_iemnet_floatlist*iemnet__chunk2list(t_iemnet_chunk*c, t_iemnet_floatlist*dest) { unsigned int i; if(NULL==c) { return NULL; } dest=iemnet__floatlist_resize(dest, c->size); if(NULL==dest) { return NULL; } for(i=0; isize; i++) { dest->argv[i].a_w.w_float = c->data[i]; } return dest; } /* queue handling */ /* * using code found at http://newsgroups.derkeiler.com/Archive/Comp/comp.programming.threads/2008-02/msg00502.html */ #ifdef t_iemnet_queue # undef t_iemnet_queue #endif typedef struct _node { struct _node* next; t_iemnet_chunk*data; } t_node; struct _iemnet_queue { t_node* head; /* = 0 */ t_node* tail; /* = 0 */ pthread_mutex_t mtx; pthread_cond_t cond; int done; // in cleanup state int size; pthread_mutex_t usedmtx; pthread_cond_t usedcond; int used; // use counter, so queue_finish can wait for blocking accesses to finish }; static void queue_use_increment(t_iemnet_queue* _this) { pthread_mutex_lock(&_this->usedmtx); _this->used++; pthread_mutex_unlock(&_this->usedmtx); } static void queue_use_decrement(t_iemnet_queue* _this) { pthread_mutex_lock(&_this->usedmtx); _this->used--; pthread_cond_signal(&_this->usedcond); pthread_mutex_unlock(&_this->usedmtx); } /* push a chunk into the queue * this will return the current queue size */ int queue_push( t_iemnet_queue* const _this, t_iemnet_chunk* const data ) { t_node* tail; t_node* n=NULL; int size=-1; if(NULL == _this) { return size; } pthread_mutex_lock(&_this->mtx); size=_this->size; pthread_mutex_unlock(&_this->mtx); if(NULL == data) { return size; } n=(t_node*)malloc(sizeof(t_node)); n->next = 0; n->data = data; pthread_mutex_lock(&_this->mtx); if (! (tail = _this->tail)) { _this->head = n; } else { tail->next = n; } _this->tail = n; _this->size+=data->size; size=_this->size; // added new chunk, so tell waiting threads that they can pop the data pthread_cond_signal(&_this->cond); pthread_mutex_unlock(&_this->mtx); return size; } /* pop a chunk from the queue * if the queue is empty, this will block until * something has been pushed * OR the queue is "done" (in which case NULL is returned) */ t_iemnet_chunk* queue_pop_block( t_iemnet_queue* const _this ) { t_node* head=0; t_iemnet_chunk*data=0; if(NULL == _this) { return NULL; } queue_use_increment(_this); pthread_mutex_lock(&_this->mtx); /* if the queue is empty, wait */ while(NULL == _this->head) { pthread_cond_wait(&_this->cond, &_this->mtx); /* somebody signaled us, that we should do some work * either the queue has been filled, or we are done... */ if(_this->done) { pthread_mutex_unlock(&_this->mtx); queue_use_decrement(_this); return NULL; } } /* save the head, below we gonna work on this */ head = _this->head; /* update _this */ if(head) { if (! (_this->head = head->next)) { _this->tail = 0; } if(head->data) { _this->size-=head->data->size; } } pthread_mutex_unlock(&_this->mtx); if(head) { data=head->data; free(head); head=NULL; } queue_use_decrement(_this); return data; } /* pop a chunk from the queue * if the queue is empty, this will immediately return NULL * (note that despite of the name this does block for synchronization) */ t_iemnet_chunk* queue_pop_noblock( t_iemnet_queue* const _this ) { t_node* head=0; t_iemnet_chunk*data=0; if(NULL == _this) { return NULL; } queue_use_increment(_this); pthread_mutex_lock(&_this->mtx); if (! (head = _this->head)) { // empty head pthread_mutex_unlock(&_this->mtx); queue_use_decrement(_this); return NULL; } if (! (_this->head = head->next)) { _this->tail = 0; } if(head && head->data) { _this->size-=head->data->size; } pthread_mutex_unlock(&_this->mtx); if(head) { data=head->data; free(head); head=NULL; } queue_use_decrement(_this); return data; } t_iemnet_chunk* queue_pop(t_iemnet_queue* const _this) { return queue_pop_block(_this); } int queue_getsize(t_iemnet_queue* const _this) { int size=-1; if(_this) { pthread_mutex_lock(&_this->mtx); size=_this->size; pthread_mutex_unlock(&_this->mtx); } return size; } void queue_finish(t_iemnet_queue* q) { DEBUG("queue_finish: %x", q); if(NULL==q) { return; } pthread_mutex_lock(&q->mtx); q->done=1; DEBUG("queue signaling: %x", q); pthread_cond_signal(&q->cond); DEBUG("queue signaled: %x", q); pthread_mutex_unlock(&q->mtx); /* wait until queue is no longer used */ pthread_mutex_lock(&q->usedmtx); while(q->used) { pthread_cond_wait(&q->usedcond, &q->usedmtx); } pthread_mutex_unlock(&q->usedmtx); DEBUG("queue_finished: %x", q); } void queue_destroy(t_iemnet_queue* q) { t_iemnet_chunk*c=NULL; if(NULL==q) { return; } DEBUG("queue destroy %x", q); queue_finish(q); /* remove all the chunks from the queue */ while(NULL!=(c=queue_pop_noblock(q))) { iemnet__chunk_destroy(c); } q->head=NULL; q->tail=NULL; pthread_mutex_destroy(&q->mtx); pthread_cond_destroy(&q->cond); pthread_mutex_destroy(&q->usedmtx); pthread_cond_destroy(&q->usedcond); free(q); q=NULL; DEBUG("queue destroyed %x", q); } t_iemnet_queue* queue_create(void) { static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; t_iemnet_queue*q=(t_iemnet_queue*)malloc(sizeof(t_iemnet_queue)); DEBUG("queue create %x", q); if(NULL==q) { return NULL; } q->head = NULL; q->tail = NULL; memcpy(&q->cond, &cond, sizeof(pthread_cond_t)); memcpy(&q->mtx , &mtx, sizeof(pthread_mutex_t)); memcpy(&q->usedcond, &cond, sizeof(pthread_cond_t)); memcpy(&q->usedmtx , &mtx, sizeof(pthread_mutex_t)); q->done = 0; q->size = 0; q->used = 0; DEBUG("queue created %x", q); return q; } pd-iemnet-0.2.1/iemnet_data.h000066400000000000000000000151611257237665700160470ustar00rootroot00000000000000/* *********************************************+ * iemnet * networking for Pd * * (c) 2010 IOhannes m zmölnig * Institute of Electronic Music and Acoustics (IEM) * University of Music and Dramatic Arts (KUG), Graz, Austria * * data handling structures * think of these as private, no need to worry about them outside the core lib */ /* ---------------------------------------------------------------------------- */ /* This program is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation; either version 2 */ /* of the License, or (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, see */ /* http://www.gnu.org/licenses/ */ /* */ /* ---------------------------------------------------------------------------- */ #ifndef INCLUDE__IEMNET_DATA_H_ #define INCLUDE__IEMNET_DATA_H_ /** * a resizable list of float-only atoms */ typedef struct _iemnet_floatlist { t_atom*argv; size_t argc; size_t size; // real size (might be bigger than argc) } t_iemnet_floatlist; /** * create a list of float-only atoms * * \param size initial size of the floatlist * \return pointer to a float-atom list or NULL of creation failed */ t_iemnet_floatlist*iemnet__floatlist_create(unsigned int size); /** * destroy a list of float-only atoms * * \param pointer to a float-atom list */ void iemnet__floatlist_destroy(t_iemnet_floatlist*cl); /** * chunk of data as sent to a socket or received from it * for received data, this might additionally hold the originator (if available) */ typedef struct _iemnet_chunk { unsigned char* data; size_t size; long addr; unsigned short port; short family; // AF_INET, AF_INET6 } t_iemnet_chunk; /** * free a "chunk" (de-allocate memory,...) */ void iemnet__chunk_destroy(t_iemnet_chunk*); /** * print a "chunk" to the pd-console */ void iemnet__chunk_print(t_iemnet_chunk*c); /** * initialize a "chunk" (allocate memory,...) of fixed size * receiver address will be set to 0 * * \param size of the chunk (data will be zeroed out) * \return a new chunk of given size */ t_iemnet_chunk*iemnet__chunk_create_empty(int); /** * initialize a "chunk" (allocate memory,...) with given data * receiver address will be set to 0 * * \param size of data * \param data of size * \return a new chunk that holds a copy of data */ t_iemnet_chunk*iemnet__chunk_create_data(int size, unsigned char*data); /** * initialize a "chunk" (allocate memory,...) with given data from specified address * \param size of data * \param data of size * \param addr originating address (can be NULL) * \return a new chunk that holds a copy of data */ t_iemnet_chunk*iemnet__chunk_create_dataaddr(int size, unsigned char*data, struct sockaddr_in*addr); /** * initialize a "chunk" (allocate memory,...) with given data * receiver address will be set to 0 * * \param argc size of list * \param argv list of atoms containing only "bytes" (t_floats [0..255]) * \return a new chunk that holds a copy of the list data */ t_iemnet_chunk*iemnet__chunk_create_list(int argc, t_atom*argv); /** * initialize a "chunk" (allocate memory,...) from another chunk * * \param src the source chunk * \return a new chunk that holds a copy of the source data */ t_iemnet_chunk*iemnet__chunk_create_chunk(t_iemnet_chunk*source); /** * convert a data chunk to a Pd-list of A_FLOATs * the destination list will eventually be resized if it is too small to hold the chunk * * \param c the chunk to convert * \param dest the destination list * \return the destination list if all went well, else NULL */ t_iemnet_floatlist*iemnet__chunk2list(t_iemnet_chunk*c, t_iemnet_floatlist*dest); /** * opaque type for a thread safe queue (FIFO) */ typedef struct _iemnet_queue t_iemnet_queue; EXTERN_STRUCT _iemnet_queue; /** * push data to the FIFO (queue) * * \param q the queue to push to * \param d the pushed data (the queue will only store the pointer to the data; so don't free it yet) * \return the fill state of the queue after the push * * \note thread safe */ int queue_push(t_iemnet_queue* const q, t_iemnet_chunk* const d); /** * \brief pop data from the FIFO (queue), blocking * * pops data from the stack; * if the stack is empty, this function will block until data is pushed to the stack * if the queue is finalized, this function will return immediately with NULL * * \param q the queue to pop from * \return pointer to the popped data; the caller is responsible for freeing the chunk * * \note thread safe */ t_iemnet_chunk* queue_pop_block(t_iemnet_queue* const q); /** * pop data from the stack (queue), non-blocking * * pops data from the stack; if the stack is empty, this function will immediately return NULL * * \param q the queue to pop from * \return pointer to the popped data or NULL; the caller is responsible for freeing the chunk * * \note thread safe */ t_iemnet_chunk* queue_pop_noblock(t_iemnet_queue* const); /** * get size if queue * * \param q the queue to get the size of * \return the fill state of the queue, -1 if something goes wrong * * \note thread safe */ int queue_getsize(t_iemnet_queue* const q); /** * initiate cleanup process * * unblocks all blocking calls to queue_pop_block(t_iemnet_queue* const q); * * \param q the queue to unblock */ void queue_finish(t_iemnet_queue* q); /** * destroy queue (FIFO) * * releases all data in the queue (by calling iemnet__chunk_destroy()) and then frees all other ressources attached to the queue * * \param q the queue to destroy */ void queue_destroy(t_iemnet_queue* q); /** * create a queue (FIFO) * * \return the newly created queue; if something went wrong NULL is returned */ t_iemnet_queue* queue_create(void); #endif /* INCLUDE__IEMNET_DATA_H_ */ pd-iemnet-0.2.1/iemnet_receiver.c000066400000000000000000000075231257237665700167400ustar00rootroot00000000000000/* iemnet * * receiver * receives data "chunks" from a socket * * copyright © 2010-2015 IOhannes m zmölnig, IEM */ /* This program is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation; either version 2 */ /* of the License, or (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, see */ /* http://www.gnu.org/licenses/ */ /* */ #define DEBUGLEVEL 4 #include "iemnet.h" #include "iemnet_data.h" #include #include #define INBUFSIZE 65536L /* was 4096: size of receiving data buffer */ struct _iemnet_receiver { int sockfd; /* owned outside; you must call iemnet__receiver_destroy() before freeing socket yourself */ void*userdata; t_iemnet_receivecallback callback; }; static void pollfun(void*z, int fd) { // read data from socket and call callback t_iemnet_receiver*rec=(t_iemnet_receiver*)z; unsigned char data[INBUFSIZE]; unsigned int size=INBUFSIZE; t_iemnet_chunk*chunk=NULL; int result = 0; int local_errno = 0; struct sockaddr_in from; socklen_t fromlen = sizeof(from); int recv_flags=0; #ifdef MSG_DONTWAIT recv_flags|=MSG_DONTWAIT; #endif errno=0; result = recvfrom(rec->sockfd, data, size, recv_flags, (struct sockaddr *)&from, &fromlen); local_errno=errno; //fprintf(stderr, "read %d bytes...\n", result); DEBUG("recvfrom %d bytes: %d %p %d", result, rec->sockfd, data, size); DEBUG("errno=%d", local_errno); chunk = iemnet__chunk_create_dataaddr(result, (result>0)?data:NULL, &from); // call the callback with a NULL-chunk to signal a disconnect event. (rec->callback)(rec->userdata, chunk); iemnet__chunk_destroy(chunk); } t_iemnet_receiver*iemnet__receiver_create(int sock, void*userdata, t_iemnet_receivecallback callback, int subthread) { t_iemnet_receiver*rec=(t_iemnet_receiver*)malloc(sizeof( t_iemnet_receiver)); DEBUG("create new receiver for 0x%X:%d", userdata, sock); //fprintf(stderr, "new receiver for %d\t%x\t%x\n", sock, userdata, callback); if(rec) { rec->sockfd=sock; rec->userdata=userdata; rec->callback=callback; if(subthread) { sys_lock(); } sys_addpollfn(sock, pollfun, rec); if(subthread) { sys_unlock(); } } //fprintf(stderr, "new receiver created\n"); return rec; } void iemnet__receiver_destroy(t_iemnet_receiver*rec, int subthread) { int sockfd; if(NULL==rec) { return; } sockfd=rec->sockfd; if(subthread) { sys_lock(); } sys_rmpollfn(rec->sockfd); // FIXXME: read any remaining bytes from the socket if(subthread) { sys_unlock(); } DEBUG("[%p] really destroying receiver %d", sockfd); DEBUG("[%p] closed socket %d", rec, sockfd); rec->sockfd=-1; rec->userdata=NULL; rec->callback=NULL; free(rec); rec=NULL; } /* just dummy, since we don't maintain a queue any more */ int iemnet__receiver_getsize(t_iemnet_receiver*x) { if(x) { return 0; } return -1; } pd-iemnet-0.2.1/iemnet_sender.c000066400000000000000000000201001257237665700163760ustar00rootroot00000000000000/* iemnet * * sender * sends data "chunks" to a socket * possibly threaded * * copyright © 2010-2015 IOhannes m zmölnig, IEM */ /* This program is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation; either version 2 */ /* of the License, or (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, see */ /* http://www.gnu.org/licenses/ */ /* */ #define DEBUGLEVEL 2 #include "iemnet.h" #include "iemnet_data.h" #include #include #include #include #include #ifdef _WIN32 # include # include /* for socklen_t */ #else # include #endif #include #if IEMNET_HAVE_DEBUG static int debug_lockcount=0; # define LOCK(x) do {if(iemnet_debug(DEBUGLEVEL, __FILE__, __LINE__, __FUNCTION__))post(" LOCKing %p", x); pthread_mutex_lock(x);debug_lockcount++; if(iemnet_debug(DEBUGLEVEL, __FILE__, __LINE__, __FUNCTION__))post(" LOCKed %p[%d]", x, debug_lockcount); } while(0) # define UNLOCK(x) do {debug_lockcount--;if(iemnet_debug(DEBUGLEVEL, __FILE__, __LINE__, __FUNCTION__))post(" UNLOCK %p [%d]", x, debug_lockcount); pthread_mutex_unlock(x);}while(0) #else # define LOCK(x) pthread_mutex_lock(x) # define UNLOCK(x) pthread_mutex_unlock(x) #endif /* draft: * - there is a sender thread for each open connection * - the main thread just adds chunks to each sender threads processing queue * - the sender thread tries to send the queue as fast as possible */ struct _iemnet_sender { pthread_t thread; int sockfd; /* owned outside; must call iemnet__sender_destroy() before freeing socket yourself */ t_iemnet_queue*queue; int keepsending; // indicates whether we want to thread to continue or to terminate int isrunning; const void*userdata; /* user provided data */ t_iemnet_sendfunction sendfun; /* user provided send function */ pthread_mutex_t mtx; /* mutex to protect isrunning,.. */ }; /* the workhorse of the family */ static int iemnet__sender_defaultsend(const void*x, int sockfd, t_iemnet_chunk*c) { int result=-1; struct sockaddr_in to; socklen_t tolen = sizeof(to); unsigned char*data=c->data; unsigned int size=c->size; int flags = 0; #ifdef __linux__ flags |= MSG_NOSIGNAL; #endif // fprintf(stderr, "sending %d bytes at %x to %d\n", size, data, sockfd); if(c->port) { DEBUG("sending %d bytes to %x:%d @%d", size, c->addr, c->port, c->family); to.sin_addr.s_addr=htonl(c->addr); to.sin_port =htons(c->port); to.sin_family =c->family; result = sendto(sockfd, data, size, /* DATA */ flags, /* FLAGS */ (struct sockaddr *)&to, tolen); /* DESTADDR */ } else { DEBUG("sending %d bytes", size); result = send(sockfd, data, size, /* DATA */ flags); /* FLAGS */ } if(result<0) { // broken pipe return 0; } // shouldn't we do something with the result here? DEBUG("sent %d bytes", result); return 1; } static void*iemnet__sender_sendthread(void*arg) { t_iemnet_sender*sender=(t_iemnet_sender*)arg; int sockfd=-1; t_iemnet_queue*q=NULL; t_iemnet_chunk*c=NULL; t_iemnet_sendfunction dosend=iemnet__sender_defaultsend; const void*userdata=NULL; LOCK(&sender->mtx); q=sender->queue; userdata=sender->userdata; if(NULL!=sender->sendfun) { dosend=sender->sendfun; } sockfd=sender->sockfd; while(sender->keepsending) { UNLOCK(&sender->mtx); c=queue_pop_block(q); if(c) { if(!dosend(userdata, sockfd, c)) { iemnet__chunk_destroy(c); LOCK(&sender->mtx); break; } iemnet__chunk_destroy(c); c=NULL; } LOCK(&sender->mtx); } sender->isrunning=0; UNLOCK (&sender->mtx); DEBUG("send thread terminated"); return NULL; } int iemnet__sender_send(t_iemnet_sender*s, t_iemnet_chunk*c) { t_iemnet_queue*q=0; int size=-1; LOCK (&s->mtx); q=s->queue; if(!s->isrunning) { UNLOCK (&s->mtx); return -1; } UNLOCK (&s->mtx); if(q) { t_iemnet_chunk*chunk=iemnet__chunk_create_chunk(c); size = queue_push(q, chunk); } return size; } void iemnet__sender_destroy(t_iemnet_sender*s, int subthread) { int sockfd=-1; /* simple protection against recursive calls: * s->keepsending is only set to "0" in here, * so if it is false, we know that we are already being called */ DEBUG("destroy sender %x with queue %x (%d)", s, s->queue, s->keepsending); LOCK (&s->mtx); sockfd=s->sockfd; // check s->isrunning DEBUG("keepsending %d\tisrunning %d", s->keepsending, s->isrunning); if(!s->keepsending) { UNLOCK (&s->mtx); return; } s->keepsending=0; while(s->isrunning) { s->keepsending=0; queue_finish(s->queue); UNLOCK (&s->mtx); LOCK (&s->mtx); } UNLOCK (&s->mtx); queue_finish(s->queue); DEBUG("queue finished"); pthread_join(s->thread, NULL); DEBUG("thread joined"); queue_destroy(s->queue); pthread_mutex_destroy (&s->mtx); memset(s, 0, sizeof(t_iemnet_sender)); s->sockfd = -1; free(s); s=NULL; DEBUG("destroyed sender"); } t_iemnet_sender*iemnet__sender_create(int sock, t_iemnet_sendfunction sendfun, const void*userdata, int subthread) { static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; t_iemnet_sender*result=(t_iemnet_sender*)calloc(1, sizeof(t_iemnet_sender)); int res=0; DEBUG("create sender %x", result); if(NULL==result) { DEBUG("create sender failed"); return NULL; } result->queue = queue_create(); result->sockfd = sock; result->keepsending =1; result->isrunning=1; result->sendfun=sendfun; result->userdata=userdata; DEBUG("create_sender queue=%x", result->queue); memcpy(&result->mtx , &mtx, sizeof(pthread_mutex_t)); res=pthread_create(&result->thread, 0, iemnet__sender_sendthread, result); if(0==res) { } else { // something went wrong queue_destroy(result->queue); free(result); return NULL; } DEBUG("created sender"); return result; } /* coverity[param_set_but_not_used]: as x is there for potentially more specific implentations in the future */ int iemnet__sender_getlasterror(t_iemnet_sender*x) { #ifdef _WIN32 return WSAGetLastError(); #endif return errno; } int iemnet__sender_getsockopt(t_iemnet_sender*s, int level, int optname, void *optval, socklen_t*optlen) { int result=getsockopt(s->sockfd, level, optname, optval, optlen); if(result!=0) { error("iemnet::sender: getsockopt returned %d", iemnet__sender_getlasterror(s)); } return result; } int iemnet__sender_setsockopt(t_iemnet_sender*s, int level, int optname, const void*optval, socklen_t optlen) { int result=setsockopt(s->sockfd, level, optname, optval, optlen); if(result!=0) { error("iemnet::sender: setsockopt returned %d", iemnet__sender_getlasterror(s)); } return result; } int iemnet__sender_getsize(t_iemnet_sender*x) { int size=-1; if(x && x->queue) { size=queue_getsize(x->queue); } return size; } pd-iemnet-0.2.1/tcpclient-help.pd000066400000000000000000000057251257237665700166710ustar00rootroot00000000000000#N canvas 3 62 1018 535 12; #X msg 134 135 disconnect; #X obj 255 328 unpack 0 0 0 0; #X floatatom 255 351 3 0 0 0 - - -; #X floatatom 286 351 3 0 0 0 - - -; #X floatatom 318 351 3 0 0 0 - - -; #X floatatom 350 351 3 0 0 0 - - -; #X text 219 351 from; #X msg 71 72 connect 132.205.142.12 80; #X obj 235 256 tcpclient; #X obj 275 307 tgl 15 0 empty empty connected 18 7 0 8 -24198 -241291 -1 0 1; #X text 187 21 connect with an IP address and port number; #X msg 46 47 connect www.concordia.ca 80; #X text 306 255 tcpclient opens a tcp socket to send and receive bytes on; #X text 44 257 See also:; #X msg 21 22 connect 127.0.0.1 9997; #X obj 45 279 tcpreceive; #X text 320 158 semicolon-terminated string for netserver or netreceive ; #X msg 159 160 send 49 127 128 51 59; #X obj 45 302 tcpserver; #X text 593 24 tcpclient can connect to a server and send and receive messages as lists of bytes. Any integer value between 0 and 255 can be transmitted or received.; #X msg 199 184 71 69 84 32 104 116 116 112 58 47 47 47 105 110 100 101 120 46 104 116 109 108 13 10; #X text 226 220 'send' prefix is optional; #X obj 235 402 spigot; #X obj 274 379 tgl 15 0 empty empty enable_print 18 7 0 8 -24198 -241291 -1 0 1; #X floatatom 797 190 9 0 0 0 - - -; #X msg 110 95 send 71 69 84 32 104 116 116 112 58 47 47 47 105 110 100 101 120 46 112 104 112 13 10 13 10; #X text 40 399 2010/03/01 Martin Peach; #X text 418 430 Attempting to print long messages can hang Pd!; #X obj 797 166 route sent; #X text 869 190 sent bytes; #X floatatom 797 347 3 0 0 0 - - -; #X floatatom 851 347 3 0 0 0 - - -; #X floatatom 824 347 3 0 0 0 - - -; #X obj 797 268 route address; #X obj 797 296 unpack f f f f f; #X floatatom 878 347 3 0 0 0 - - -; #X floatatom 906 321 6 0 0 0 - - -; #X text 904 347 ip; #X text 952 320 port; #X obj 235 431 print tcpclient:received; #X obj 520 344 spigot; #X obj 559 321 tgl 15 0 empty empty enable_print 18 7 0 8 -24198 -241291 -1 0 1; #X obj 520 373 print tcpclient:status; #X text 286 401 Received messages are output as a stream of bytes; #X text 515 103 GET http://index.phpCRLF; #X text 45 477 NOTE: outlet's #2 & #3 are for compatibility with mrpeach's net objects. all information is available via outlet#4 as well!; #X text 41 414 2010/10/08 Roman Haefeli; #X obj 295 281 s \$0.tcpclient.o4; #X obj 520 298 r \$0.tcpclient.o4; #X obj 797 242 r \$0.tcpclient.o4; #X obj 797 142 r \$0.tcpclient.o4; #X connect 0 0 8 0; #X connect 1 0 2 0; #X connect 1 1 3 0; #X connect 1 2 4 0; #X connect 1 3 5 0; #X connect 7 0 8 0; #X connect 8 0 22 0; #X connect 8 1 1 0; #X connect 8 2 9 0; #X connect 8 3 47 0; #X connect 11 0 8 0; #X connect 14 0 8 0; #X connect 17 0 8 0; #X connect 20 0 8 0; #X connect 22 0 39 0; #X connect 23 0 22 1; #X connect 25 0 8 0; #X connect 28 0 24 0; #X connect 33 0 34 0; #X connect 34 0 30 0; #X connect 34 1 32 0; #X connect 34 2 31 0; #X connect 34 3 35 0; #X connect 34 4 36 0; #X connect 40 0 42 0; #X connect 41 0 40 1; #X connect 48 0 40 0; #X connect 49 0 33 0; #X connect 50 0 28 0; pd-iemnet-0.2.1/tcpclient.c000066400000000000000000000232451257237665700155570ustar00rootroot00000000000000/* tcpclient.c * copyright © 2010-2015 IOhannes m zmölnig, IEM * copyright (c) 2006-2010 Martin Peach * copyright (c) 2004 Olaf Matthes */ /* */ /* A client for bidirectional communication from within Pd. */ /* */ /* This program is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation; either version 2 */ /* of the License, or (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, see */ /* http://www.gnu.org/licenses/ */ /* */ /* ---------------------------------------------------------------------------- */ #define DEBUGLEVEL 1 #include "iemnet.h" #include static t_class *tcpclient_class; static char objName[] = "tcpclient"; typedef struct _tcpclient { t_object x_obj; t_clock *x_clock; t_outlet *x_msgout; t_outlet *x_addrout; t_outlet *x_connectout; t_outlet *x_statusout; t_iemnet_sender *x_sender; t_iemnet_receiver*x_receiver; int x_serialize; int x_fd; // the socket char *x_hostname; // address we want to connect to as text int x_connectstate; // 0 = not connected, 1 = connected int x_port; // port we're connected to long x_addr; // address we're connected to as 32bit int t_iemnet_floatlist *x_floatlist; } t_tcpclient; static void tcpclient_receive_callback(void *x, t_iemnet_chunk*); static void tcpclient_info(t_tcpclient *x) { // "server " // "bufsize " static t_atom output_atom[3]; if(x&&x->x_connectstate) { int sockfd = x->x_fd; unsigned short port = x->x_port; const char*hostname=x->x_hostname; int insize =iemnet__receiver_getsize(x->x_receiver); int outsize=iemnet__sender_getsize (x->x_sender ); SETFLOAT (output_atom+0, sockfd); SETSYMBOL(output_atom+1, gensym(hostname)); SETFLOAT (output_atom+2, port); outlet_anything( x->x_statusout, gensym("server"), 3, output_atom); SETFLOAT (output_atom+0, insize); SETFLOAT (output_atom+1, outsize); outlet_anything( x->x_statusout, gensym("bufsize"), 2, output_atom); } } /* connection handling */ static int tcpclient_do_disconnect(int fd, t_iemnet_sender*sender, t_iemnet_receiver*receiver) { if(sender) { iemnet__sender_destroy(sender, 0); sender=NULL; } if(receiver) { iemnet__receiver_destroy(receiver, 0); receiver=NULL; } if (fd >= 0) { iemnet__closesocket(fd, 1); return 1; } return 0; } static int tcpclient_do_connect(const char*host, unsigned short port, t_tcpclient*x, t_iemnet_sender**senderOUT, t_iemnet_receiver**receiverOUT, long*addrOUT) { struct sockaddr_in server; struct hostent *hp; int sockfd=-1; t_iemnet_sender* sender; t_iemnet_receiver*receiver; /* connect socket using hostname provided in command line */ memset(&server, 0, sizeof(server)); server.sin_family = AF_INET; hp = gethostbyname(host); if (hp == 0) { iemnet_log(x, IEMNET_ERROR, "bad host '%s'?", host); return (-1); } memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { iemnet_log(x, IEMNET_ERROR, "unable to open socket"); sys_sockerror("socket"); return (sockfd); } /* assign client port number */ server.sin_port = htons((u_short)port); /* try to connect */ if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) { iemnet_log(x, IEMNET_ERROR, "unable to connect to stream socket"); sys_sockerror("connect"); iemnet__closesocket(sockfd, 1); return (-1); } sender=iemnet__sender_create(sockfd, NULL, NULL, 0); receiver=iemnet__receiver_create(sockfd, x, tcpclient_receive_callback, 0); if(addrOUT) { *addrOUT= ntohl(*(long *)hp->h_addr); } if(senderOUT) { *senderOUT=sender; } if(receiverOUT) { *receiverOUT=receiver; } return sockfd; } static void tcpclient_tick(t_tcpclient *x) { outlet_float(x->x_connectout, 1); } static void tcpclient_disconnect(t_tcpclient *x); static void tcpclient_connect(t_tcpclient *x, t_symbol *hostname, t_floatarg fportno) { long addr=0; int state; // first disconnect any active connection if(x->x_hostname || x->x_port) { state=tcpclient_do_disconnect(x->x_fd, x->x_sender, x->x_receiver); if(state) { outlet_float(x->x_connectout, 0); } } /* we get hostname and port and pass them on to the child thread that establishes the connection */ x->x_hostname = hostname->s_name; x->x_port = fportno; state=tcpclient_do_connect(x->x_hostname, x->x_port, x, &x->x_sender, &x->x_receiver, &x->x_addr); x->x_connectstate=(state>0); x->x_fd=state; if(state>0) { outlet_float(x->x_connectout, 1); } } static void tcpclient_disconnect(t_tcpclient *x) { if(x->x_hostname || x->x_port) { int state=tcpclient_do_disconnect(x->x_fd, x->x_sender, x->x_receiver); if(!state && !x->x_port) { iemnet_log(x, IEMNET_ERROR, "not connected"); } } outlet_float(x->x_connectout, 0); x->x_port=0; x->x_hostname=NULL; } /* sending/receiving */ static void tcpclient_send(t_tcpclient *x, t_symbol *s, int argc, t_atom *argv) { int size=0; t_atom output_atom; t_iemnet_sender*sender=x->x_sender; t_iemnet_chunk*chunk=iemnet__chunk_create_list(argc, argv); if(sender && chunk) { size=iemnet__sender_send(sender, chunk); } iemnet__chunk_destroy(chunk); SETFLOAT(&output_atom, size); outlet_anything( x->x_statusout, gensym("sendbuffersize"), 1, &output_atom); if(size<0) { tcpclient_disconnect(x); } } static void tcpclient_receive_callback(void*y, t_iemnet_chunk*c) { t_tcpclient *x=(t_tcpclient*)y; if(c) { iemnet__addrout(x->x_statusout, x->x_addrout, x->x_addr, x->x_port); x->x_floatlist=iemnet__chunk2list(c, x->x_floatlist); // get's destroyed in the dtor iemnet__streamout(x->x_msgout, x->x_floatlist->argc, x->x_floatlist->argv, x->x_serialize); } else { // disconnected tcpclient_disconnect(x); } } static void tcpclient_serialize(t_tcpclient *x, t_floatarg doit) { x->x_serialize=doit; } /* constructor/destructor */ static void tcpclient_free_simple(t_tcpclient *x) { if(x->x_clock) { clock_free(x->x_clock); } x->x_clock=NULL; if(x->x_floatlist) { iemnet__floatlist_destroy(x->x_floatlist); } x->x_floatlist=NULL; if(x->x_msgout) { outlet_free(x->x_msgout); } if(x->x_addrout) { outlet_free(x->x_addrout); } if(x->x_connectout) { outlet_free(x->x_connectout); } if(x->x_statusout) { outlet_free(x->x_statusout); } } static void *tcpclient_new(void) { t_tcpclient *x = (t_tcpclient *)pd_new(tcpclient_class); x->x_msgout = outlet_new(&x->x_obj, 0); /* received data */ x->x_addrout = outlet_new(&x->x_obj, gensym("list")); x->x_connectout = outlet_new(&x->x_obj, gensym("float")); /* connection state */ x->x_statusout = outlet_new(&x->x_obj, 0);/* last outlet for everything else */ x->x_serialize=1; x->x_fd = -1; x->x_addr = 0L; x->x_port = 0; x->x_sender=NULL; x->x_receiver=NULL; x->x_clock = clock_new(x, (t_method)tcpclient_tick); x->x_floatlist=iemnet__floatlist_create(1024); return (x); } static void tcpclient_free(t_tcpclient *x) { tcpclient_disconnect(x); tcpclient_free_simple(x); } IEMNET_EXTERN void tcpclient_setup(void) { if(!iemnet__register(objName)) { return; } tcpclient_class = class_new(gensym(objName), (t_newmethod)tcpclient_new, (t_method)tcpclient_free, sizeof(t_tcpclient), 0, A_DEFFLOAT, 0); class_addmethod(tcpclient_class, (t_method)tcpclient_connect, gensym("connect") , A_SYMBOL, A_FLOAT, 0); class_addmethod(tcpclient_class, (t_method)tcpclient_disconnect, gensym("disconnect"), 0); class_addmethod(tcpclient_class, (t_method)tcpclient_serialize, gensym("serialize"), A_FLOAT, 0); class_addmethod(tcpclient_class, (t_method)tcpclient_send, gensym("send"), A_GIMME, 0); class_addlist(tcpclient_class, (t_method)tcpclient_send); class_addbang(tcpclient_class, (t_method)tcpclient_info); DEBUGMETHOD(tcpclient_class); } IEMNET_INITIALIZER(tcpclient_setup); /* end of tcpclient.c */ pd-iemnet-0.2.1/tcpreceive-help.pd000066400000000000000000000036431257237665700170320ustar00rootroot00000000000000#N canvas 162 156 680 353 12; #X text 10 10 tcpreceive receives bytes over a tcp connection.; #X msg 20 69 port 10000; #X text 134 104 1st argument: port number; #X text 102 68 reset port number; #X floatatom 54 238 3 0 0 0 - - -; #X floatatom 108 238 3 0 0 0 - - -; #X floatatom 81 238 3 0 0 0 - - -; #X obj 54 187 unpack f f f f f; #X floatatom 135 238 3 0 0 0 - - -; #X floatatom 163 212 6 0 0 0 - - -; #X text 161 238 ip; #X text 209 212 port; #X text 178 188 from; #X obj 20 270 print tcpreceive:received; #X floatatom 88 160 3 0 0 0 - - -; #X text 114 160 connections; #X obj 122 137 s \$0.tcpreceive.o3; #X obj 253 242 spigot; #X obj 292 222 tgl 15 0 empty empty enable_print 17 7 0 10 -24198 -258699 -45076 0 1; #X obj 253 197 r \$0.tcpreceive.o3; #X obj 253 268 print tcpreceive:status; #X floatatom 483 121 3 0 0 0 - - -; #X floatatom 537 121 3 0 0 0 - - -; #X floatatom 510 121 3 0 0 0 - - -; #X obj 483 41 route address; #X obj 483 70 unpack f f f f f; #X floatatom 564 121 3 0 0 0 - - -; #X floatatom 592 95 6 0 0 0 - - -; #X text 590 121 ip; #X text 638 95 port; #X obj 483 15 r \$0.tcpreceive.o3; #X obj 483 165 r \$0.tcpreceive.o3; #X obj 483 191 route port; #X floatatom 483 217 6 0 0 0 - - -; #X text 532 217 port; #X obj 20 105 tcpreceive 9997; #X text 15 310 NOTE: outlet's #2 & #3 are for compatibility with mrpeach's net objects. all information is available via outlet#4 as well!; #X obj 500 286 tcpsend; #X obj 500 311 tcpserver; #X text 499 263 check also:; #X connect 1 0 35 0; #X connect 7 0 4 0; #X connect 7 1 6 0; #X connect 7 2 5 0; #X connect 7 3 8 0; #X connect 7 4 9 0; #X connect 17 0 20 0; #X connect 18 0 17 1; #X connect 19 0 17 0; #X connect 24 0 25 0; #X connect 25 0 21 0; #X connect 25 1 23 0; #X connect 25 2 22 0; #X connect 25 3 26 0; #X connect 25 4 27 0; #X connect 30 0 24 0; #X connect 31 0 32 0; #X connect 32 0 33 0; #X connect 35 0 13 0; #X connect 35 1 7 0; #X connect 35 2 14 0; #X connect 35 3 16 0; pd-iemnet-0.2.1/tcpreceive.c000066400000000000000000000253441257237665700157250ustar00rootroot00000000000000/* tcpreceive.c * copyright © 2010-2015 IOhannes m zmölnig, IEM * copyright (c) 2006-2010 Martin Peach * copyright (c) Miller Puckette */ /* */ /* A client for unidirectional communication from within Pd. */ /* */ /* This program is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation; either version 2 */ /* of the License, or (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, see */ /* http://www.gnu.org/licenses/ */ /* */ #define DEBUGLEVEL 1 static const char*objName="tcpreceive"; #include "iemnet.h" #ifndef _WIN32 /* needed for TCP_NODELAY */ # include #endif #include /* ----------------------------- tcpreceive ------------------------- */ static t_class *tcpreceive_class; #define MAX_CONNECTIONS 128 // this is going to cause trouble down the line...:( typedef struct _tcpconnection { long addr; unsigned short port; int socket; struct _tcpreceive*owner; t_iemnet_receiver*receiver; } t_tcpconnection; typedef struct _tcpreceive { t_object x_obj; t_outlet *x_msgout; t_outlet *x_addrout; t_outlet *x_connectout; t_outlet *x_statout; int x_connectsocket; int x_port; int x_serialize; int x_nconnections; t_tcpconnection x_connection[MAX_CONNECTIONS]; t_iemnet_floatlist *x_floatlist; } t_tcpreceive; /* forward declarations */ static int tcpreceive_disconnect(t_tcpreceive *x, int id); static int tcpreceive_find_socket(t_tcpreceive *x, int fd) { int i; for (i = 0; i < MAX_CONNECTIONS; ++i) if (x->x_connection[i].socket == fd) { return i; } return -1; } static void tcpreceive_read_callback(void *w, t_iemnet_chunk*c) { t_tcpconnection*y=(t_tcpconnection*)w; t_tcpreceive*x=NULL; int index=-1; if(NULL==y || NULL==(x=y->owner)) { return; } index=tcpreceive_find_socket(x, y->socket); if(index>=0) { if(c) { // TODO?: outlet info about connection x->x_floatlist=iemnet__chunk2list(c, x->x_floatlist); // gets destroyed in the dtor iemnet__streamout(x->x_msgout, x->x_floatlist->argc, x->x_floatlist->argv, x->x_serialize); } else { // disconnected tcpreceive_disconnect(x, index); } } } /* tcpreceive_addconnection tries to add the socket fd to the list */ /* returns 1 on success, else 0 */ static int tcpreceive_addconnection(t_tcpreceive *x, int fd, long addr, unsigned short port) { int i; for (i = 0; i < MAX_CONNECTIONS; ++i) { if (x->x_connection[i].socket == -1) { x->x_connection[i].socket = fd; x->x_connection[i].addr = addr; x->x_connection[i].port = port; x->x_connection[i].owner = x; x->x_connection[i].receiver= iemnet__receiver_create(fd, x->x_connection+i, tcpreceive_read_callback, 0); return 1; } } return 0; } /* tcpreceive_connectpoll checks for incoming connection requests on the original socket */ /* a new socket is assigned */ static void tcpreceive_connectpoll(t_tcpreceive *x) { struct sockaddr_in from; socklen_t fromlen = sizeof(from); long addr; unsigned short port; int fd; fd = accept(x->x_connectsocket, (struct sockaddr *)&from, &fromlen); if (fd < 0) { iemnet_log(x, IEMNET_ERROR, "could not accept new connection"); sys_sockerror("accept"); } else { /* get the sender's ip */ addr = ntohl(from.sin_addr.s_addr); port = ntohs(from.sin_port); if (tcpreceive_addconnection(x, fd, addr, port)) { x->x_nconnections++; outlet_float(x->x_connectout, x->x_nconnections); iemnet__addrout(x->x_statout, x->x_addrout, addr, port); } else { iemnet_log(x, IEMNET_ERROR, "too many connections"); iemnet__closesocket(fd, 1); } } } static int tcpreceive_disconnect(t_tcpreceive *x, int id) { if(id>=0 && id < MAX_CONNECTIONS && x->x_connection[id].port>0) { iemnet__receiver_destroy(x->x_connection[id].receiver, 0); x->x_connection[id].receiver=NULL; iemnet__closesocket(x->x_connection[id].socket, 1); x->x_connection[id].socket = -1; x->x_connection[id].addr = 0L; x->x_connection[id].port = 0; x->x_nconnections--; outlet_float(x->x_connectout, x->x_nconnections); return 1; } return 0; } /* tcpreceive_closeall closes all open sockets and deletes them from the list */ static void tcpreceive_disconnect_all(t_tcpreceive *x) { int i; for (i = 0; i < MAX_CONNECTIONS; i++) { tcpreceive_disconnect(x, i); } } /* tcpreceive_removeconnection tries to delete the socket fd from the list */ /* returns 1 on success, else 0 */ static int tcpreceive_disconnect_socket(t_tcpreceive *x, int fd) { int i; for (i = 0; i < MAX_CONNECTIONS; ++i) { if (x->x_connection[i].socket == fd) { return tcpreceive_disconnect(x, i); } } return 0; } static void tcpreceive_port(t_tcpreceive*x, t_floatarg fportno) { static t_atom ap[1]; int portno = fportno; struct sockaddr_in server; socklen_t serversize=sizeof(server); int sockfd = x->x_connectsocket; int intarg; memset(&server, 0, sizeof(server)); SETFLOAT(ap, -1); if(x->x_port == portno) { return; } /* cleanup any open ports */ if(sockfd>=0) { sys_rmpollfn(sockfd); iemnet__closesocket(sockfd, 1); x->x_connectsocket=-1; x->x_port=-1; } sockfd = socket(AF_INET, SOCK_STREAM, 0); if(sockfd<0) { iemnet_log(x, IEMNET_ERROR, "unable to create socket"); sys_sockerror("socket"); return; } /* ask OS to allow another Pd to reopen this port after we close it. */ #ifdef SO_REUSEADDR intarg = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&intarg, sizeof(intarg)) < 0) { iemnet_log(x, IEMNET_ERROR, "unable to enable address re-using"); sys_sockerror("setsockopt:SO_REUSEADDR"); } #endif /* SO_REUSEADDR */ #ifdef SO_REUSEPORT intarg = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (char *)&intarg, sizeof(intarg)) < 0) { iemnet_log(x, IEMNET_ERROR, "unable to enable port re-using"); sys_sockerror("setsockopt:SO_REUSEPORT"); } #endif /* SO_REUSEPORT */ /* Stream (TCP) sockets are set NODELAY */ intarg = 1; if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&intarg, sizeof(intarg)) < 0) { iemnet_log(x, IEMNET_ERROR, "unable to enable immediate sending"); sys_sockerror("setsockopt:TCP_NODELAY"); } server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons((u_short)portno); /* name the socket */ if (bind(sockfd, (struct sockaddr *)&server, serversize) < 0) { iemnet_log(x, IEMNET_ERROR, "couldn't bind socket"); sys_sockerror("bind"); iemnet__closesocket(sockfd, 1); sockfd = -1; outlet_anything(x->x_statout, gensym("port"), 1, ap); return; } /* streaming protocol */ if (listen(sockfd, 5) < 0) { iemnet_log(x, IEMNET_ERROR, "unable to listen on socket"); sys_sockerror("listen"); iemnet__closesocket(sockfd, 1); sockfd = -1; outlet_anything(x->x_statout, gensym("port"), 1, ap); return; } else { sys_addpollfn(sockfd, (t_fdpollfn)tcpreceive_connectpoll, x); // wait for new connections } x->x_connectsocket = sockfd; x->x_port = portno; // find out which port is actually used (useful when assigning "0") if(!getsockname(sockfd, (struct sockaddr *)&server, &serversize)) { x->x_port=ntohs(server.sin_port); } SETFLOAT(ap, x->x_port); outlet_anything(x->x_statout, gensym("port"), 1, ap); } static void tcpreceive_serialize(t_tcpreceive *x, t_floatarg doit) { x->x_serialize=doit; } static void tcpreceive_free(t_tcpreceive *x) { /* is this ever called? */ if (x->x_connectsocket >= 0) { sys_rmpollfn(x->x_connectsocket); iemnet__closesocket(x->x_connectsocket, 1); } tcpreceive_disconnect_all(x); if(x->x_floatlist) { iemnet__floatlist_destroy(x->x_floatlist); } x->x_floatlist=NULL; } static void *tcpreceive_new(t_floatarg fportno) { t_tcpreceive *x; int portno = fportno; int i; x = (t_tcpreceive *)pd_new(tcpreceive_class); x->x_msgout = outlet_new(&x->x_obj, 0); x->x_addrout = outlet_new(&x->x_obj, gensym("list")); /* legacy */ x->x_connectout = outlet_new(&x->x_obj, gensym("float")); /* legacy */ x->x_statout = outlet_new(&x->x_obj, 0); /* outlet for everything else */ x->x_serialize=1; x->x_connectsocket=-1; x->x_port=-1; x->x_nconnections=0; /* clear the connection list */ for (i = 0; i < MAX_CONNECTIONS; ++i) { x->x_connection[i].socket = -1; x->x_connection[i].addr = 0L; x->x_connection[i].port = 0; } x->x_floatlist=iemnet__floatlist_create(1024); tcpreceive_port(x, portno); return (x); } IEMNET_EXTERN void tcpreceive_setup(void) { if(!iemnet__register(objName)) { return; } tcpreceive_class = class_new(gensym(objName), (t_newmethod)tcpreceive_new, (t_method)tcpreceive_free, sizeof(t_tcpreceive), 0, A_DEFFLOAT, 0); class_addmethod(tcpreceive_class, (t_method)tcpreceive_port, gensym("port"), A_DEFFLOAT, 0); class_addmethod(tcpreceive_class, (t_method)tcpreceive_serialize, gensym("serialize"), A_FLOAT, 0); DEBUGMETHOD(tcpreceive_class); } IEMNET_INITIALIZER(tcpreceive_setup); /* end x_net_tcpreceive.c */ pd-iemnet-0.2.1/tcpsend-help.pd000066400000000000000000000011621257237665700163330ustar00rootroot00000000000000#N canvas 0 92 506 250 12; #X msg 109 130 disconnect; #X obj 145 209 tgl 15 0 empty empty connected 20 7 0 8 -24198 -241291 -1 0 1; #X obj 145 186 tcpsend; #X msg 47 68 send 0 1 2 3; #X text 14 7 tcpsend sends bytes over a tcp connection.; #X text 142 68 send raw data; #X text 140 97 'send' prefix is optional; #X msg 75 96 99 98 97; #X text 181 35 <--first connect; #X text 289 173 2007/06/20 Martin Peach; #X msg 15 36 connect 127.0.0.1 9997; #X obj 364 55 tcpclient; #X obj 364 81 tcpreceive; #X text 359 32 check also:; #X connect 0 0 2 0; #X connect 2 0 1 0; #X connect 3 0 2 0; #X connect 7 0 2 0; #X connect 10 0 2 0; pd-iemnet-0.2.1/tcpsend.c000066400000000000000000000121311257237665700152220ustar00rootroot00000000000000/* tcpsend.c * copyright © 2010-2015 IOhannes m zmölnig, IEM * copyright (c) 2006-2010 Martin Peach * copyright (c) Miller Puckette */ /* */ /* A client for unidirectional communication from within Pd. */ /* */ /* This program is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation; either version 2 */ /* of the License, or (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, see */ /* http://www.gnu.org/licenses/ */ /* */ #define DEBUGLEVEL 1 static const char objName[] = "tcpsend"; #include "iemnet.h" #include #ifndef _WIN32 # include #endif static t_class *tcpsend_class; typedef struct _tcpsend { t_object x_obj; int x_fd; t_iemnet_sender*x_sender; } t_tcpsend; static void tcpsend_disconnect(t_tcpsend *x) { if(x->x_sender) { iemnet__sender_destroy(x->x_sender, 0); } x->x_sender=NULL; if (x->x_fd >= 0) { iemnet__closesocket(x->x_fd, 1); x->x_fd = -1; outlet_float(x->x_obj.ob_outlet, 0); } } static void tcpsend_connect(t_tcpsend *x, t_symbol *hostname, t_floatarg fportno) { struct sockaddr_in server; struct hostent *hp; int sockfd; int portno = fportno; int intarg; memset(&server, 0, sizeof(server)); if (x->x_fd >= 0) { iemnet_log(x, IEMNET_ERROR, "already connected"); return; } /* resolve hostname provided as argument */ server.sin_family = AF_INET; hp = gethostbyname(hostname->s_name); if (hp == 0) { iemnet_log(x, IEMNET_ERROR, "bad host '%s'?", hostname->s_name); return; } /* create a socket */ sockfd = socket(AF_INET, SOCK_STREAM, 0); DEBUG("send socket %d\n", sockfd); if (sockfd < 0) { iemnet_log(x, IEMNET_ERROR, "unable to open socket"); sys_sockerror("socket"); return; } /* for stream (TCP) sockets, specify "nodelay" */ intarg = 1; if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&intarg, sizeof(intarg)) < 0) { iemnet_log(x, IEMNET_ERROR, "unable to enable immediate sending"); sys_sockerror("setsockopt"); } /* connect socket using hostname provided as argument */ memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); /* assign client port number */ server.sin_port = htons((u_short)portno); iemnet_log(x, IEMNET_VERBOSE, "connecting to port %d", portno); /* try to connect. */ if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) { iemnet_log(x, IEMNET_ERROR, "unable to initiate connection on socket %d", sockfd); sys_sockerror("connect"); iemnet__closesocket(sockfd, 1); return; } x->x_fd = sockfd; x->x_sender=iemnet__sender_create(sockfd, NULL, NULL, 0); outlet_float(x->x_obj.ob_outlet, 1); } static void tcpsend_send(t_tcpsend *x, t_symbol *s, int argc, t_atom *argv) { int size=0; t_iemnet_sender*sender=x->x_sender; t_iemnet_chunk*chunk=iemnet__chunk_create_list(argc, argv); if(sender && chunk) { size=iemnet__sender_send(sender, chunk); } iemnet__chunk_destroy(chunk); } static void tcpsend_free(t_tcpsend *x) { tcpsend_disconnect(x); } static void *tcpsend_new(void) { t_tcpsend *x = (t_tcpsend *)pd_new(tcpsend_class); outlet_new(&x->x_obj, gensym("float")); x->x_fd = -1; return (x); } IEMNET_EXTERN void tcpsend_setup(void) { if(!iemnet__register(objName)) { return; } tcpsend_class = class_new(gensym(objName), (t_newmethod)tcpsend_new, (t_method)tcpsend_free, sizeof(t_tcpsend), 0, 0); class_addmethod(tcpsend_class, (t_method)tcpsend_connect, gensym("connect"), A_SYMBOL, A_FLOAT, 0); class_addmethod(tcpsend_class, (t_method)tcpsend_disconnect, gensym("disconnect"), 0); class_addmethod(tcpsend_class, (t_method)tcpsend_send, gensym("send"), A_GIMME, 0); class_addlist(tcpsend_class, (t_method)tcpsend_send); DEBUGMETHOD(tcpsend_class); } IEMNET_INITIALIZER(tcpsend_setup); /* end tcpsend.c */ pd-iemnet-0.2.1/tcpserver-help.pd000066400000000000000000000133551257237665700167170ustar00rootroot00000000000000#N canvas 3 45 909 548 12; #X floatatom 118 299 5 0 0 0 - - -; #X floatatom 142 329 5 0 0 0 - - -; #X floatatom 166 379 3 0 0 0 - - -; #X floatatom 193 379 3 0 0 0 - - -; #X floatatom 220 379 3 0 0 0 - - -; #X floatatom 247 379 3 0 0 0 - - -; #X text 129 378 from; #X text 34 299 connections; #X msg 209 110 broadcast 1 2 3; #X text 326 108 send to all clients; #X text 72 329 on socket; #X text 202 265 argument is port number; #X text 92 490 ***WARNING*** Attempting to print long messages can hang pd!; #X obj 95 430 spigot; #X obj 134 410 tgl 15 0 empty empty enable_print 17 7 0 10 -24198 -258699 -45076 0 1; #X obj 95 266 tcpserver 9997; #X text 21 6 [tcpserver] waits for clients to connect to its port. ; #X text 94 473 Received messages are output as stream of bytes; #X obj 95 453 print tcpserver:received; #X msg 234 135 11 216 43; #X obj 324 428 spigot; #X obj 363 408 tgl 15 0 empty empty enable_print 17 7 0 10 -24198 -258699 -45076 0 1; #X obj 324 454 print tcpserver:status; #N canvas 3 45 450 300 per.socket 0; #X obj 93 254 outlet; #X msg 93 154 disconnectsocket \$1; #X floatatom 111 108 5 0 0 0 - - -; #X obj 93 131 f; #X obj 93 112 bng 15 250 50 0 empty empty empty 17 7 0 10 -258699 -241291 -1; #X msg 123 184 send 504 1 2 3; #X text 233 183 send to client on socket 504; #X text 242 153 disconnect by socket number; #X connect 1 0 0 0; #X connect 2 0 3 1; #X connect 3 0 1 0; #X connect 4 0 3 0; #X connect 5 0 0 0; #X restore 88 91 pd per.socket; #N canvas 3 45 492 322 per.client 0; #X obj 20 224 outlet; #X msg 20 81 disconnectclient \$1; #X floatatom 38 32 5 0 0 0 - - -; #X obj 20 57 f; #X obj 20 38 bng 15 250 50 0 empty empty empty 17 7 0 10 -258699 -241291 -1; #X msg 75 136 client; #X msg 50 111 client 1; #X text 118 110 get state of client 1; #X text 127 136 get state of all clients (list on right outlet); #X text 162 81 disconnect by client number; #X msg 100 161 client 1 1 2 3 4; #X text 228 160 send (binary) 1 2 3 4 to client 1; #X connect 1 0 0 0; #X connect 2 0 3 1; #X connect 3 0 1 0; #X connect 4 0 3 0; #X connect 5 0 0 0; #X connect 6 0 0 0; #X connect 10 0 0 0; #X restore 38 66 pd per.client; #X msg 245 227 disconnect; #X text 325 225 disconnect all clients; #N canvas 313 127 698 341 default.targets 1; #X obj 106 268 outlet; #X msg 106 82 target 1; #X msg 157 240 64 64 64 10; #X text 173 83 per default \, send only to client #1; #X text 244 241 send to the default target; #X msg 63 43 target; #X msg 116 112 target -2; #X text 187 113 per default \, send to all clients but #2; #X msg 133 156 targetsocket 7; #X text 245 154 per default \, send only to client on socket 7; #X msg 143 186 targetsocket -504; #X text 272 186 per default \, send to all clients but the one on socket 504; #X text 120 41 per default \, send to all connected clients (aka 'broadcast') ; #X connect 1 0 0 0; #X connect 2 0 0 0; #X connect 5 0 0 0; #X connect 6 0 0 0; #X connect 8 0 0 0; #X connect 10 0 0 0; #X restore 247 174 pd default.targets; #X text 308 139 without specified method 'broadcast' is assumed (see default.targets); #N canvas 3 45 768 526 getting.info 0; #X floatatom 99 162 5 0 0 0 - - -; #X text 139 163 to_client; #X floatatom 390 165 3 0 0 0 - - -; #X symbolatom 422 140 15 0 0 0 - - -; #X floatatom 359 189 5 0 0 0 - - -; #X floatatom 454 115 7 0 0 0 - - -; #X floatatom 180 117 5 0 0 0 - - -; #X text 223 118 on_socket; #X floatatom 139 141 5 0 0 0 - - -; #X obj 99 62 route sent; #X obj 359 61 route client; #X text 533 141 ip; #X text 505 115 port; #X text 416 165 socket; #X text 400 191 client; #X text 184 140 sent_bytes; #X floatatom 99 342 5 0 0 0 - - -; #X floatatom 180 297 5 0 0 0 - - -; #X floatatom 139 321 5 0 0 0 - - -; #X obj 99 242 route bufsize; #X floatatom 93 501 3 0 0 0 - - -; #X floatatom 147 501 3 0 0 0 - - -; #X floatatom 120 501 3 0 0 0 - - -; #X obj 93 421 route address; #X obj 99 271 unpack f f f; #X obj 359 87 unpack f f s f; #X obj 99 91 unpack f f f; #X obj 93 450 unpack f f f f f; #X floatatom 174 501 3 0 0 0 - - -; #X floatatom 202 475 6 0 0 0 - - -; #X text 200 501 ip; #X text 248 475 port; #X text 139 342 socket; #X text 178 322 insize (bytes); #X text 218 298 outsize (bytes); #X text 361 261 info about current inqueue/outqueue; #X obj 99 216 r \$0.tcpserver.o5; #X obj 93 395 r \$0.tcpserver.o5; #X obj 99 36 r \$0.tcpserver.o5; #X obj 359 35 r \$0.tcpserver.o5; #X text 354 435 NOTE: outlets #3 and #4 are for compatibility with mrpeach's net obects. You can get all information via outlet #5 as well; #X connect 9 0 26 0; #X connect 10 0 25 0; #X connect 19 0 24 0; #X connect 23 0 27 0; #X connect 24 0 16 0; #X connect 24 1 18 0; #X connect 24 2 17 0; #X connect 25 0 4 0; #X connect 25 1 2 0; #X connect 25 2 3 0; #X connect 25 3 5 0; #X connect 26 0 0 0; #X connect 26 1 8 0; #X connect 26 2 6 0; #X connect 27 0 20 0; #X connect 27 1 22 0; #X connect 27 2 21 0; #X connect 27 3 28 0; #X connect 27 4 29 0; #X connect 36 0 19 0; #X connect 37 0 23 0; #X connect 38 0 9 0; #X connect 39 0 10 0; #X restore 589 375 pd getting.info; #X text 602 456 copyright (c) 2009 Martin Peach; #X text 602 473 copyright (c) 2010 Roman Haefeli; #X text 602 490 copyright (c) 2010 IOhannes m zmoelnig; #X obj 190 293 s \$0.tcpserver.o5; #X obj 324 383 r \$0.tcpserver.o5; #X text 644 232 check also:; #X obj 647 254 tcpreceive; #X obj 647 279 tcpclient; #X obj 166 356 unpack f f f f f; #X floatatom 275 379 6 0 0 0 - - -; #X connect 8 0 15 0; #X connect 13 0 18 0; #X connect 14 0 13 1; #X connect 15 0 13 0; #X connect 15 1 0 0; #X connect 15 2 1 0; #X connect 15 3 38 0; #X connect 15 4 33 0; #X connect 19 0 15 0; #X connect 20 0 22 0; #X connect 21 0 20 1; #X connect 23 0 15 0; #X connect 24 0 15 0; #X connect 25 0 15 0; #X connect 27 0 15 0; #X connect 34 0 20 0; #X connect 38 0 2 0; #X connect 38 1 3 0; #X connect 38 2 4 0; #X connect 38 3 5 0; #X connect 38 4 39 0; pd-iemnet-0.2.1/tcpserver.c000066400000000000000000000533051257237665700156070ustar00rootroot00000000000000/* tcpserver.c * copyright © 2010-2015 IOhannes m zmölnig, IEM * copyright (c) 2006-2010 Martin Peach * copyright (c) 2004 Olaf Matthes */ /* */ /* A server for bidirectional communication from within Pd. */ /* Allows to send back data to specific clients connected to the server. */ /* */ /* This program is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation; either version 2 */ /* of the License, or (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, see */ /* http://www.gnu.org/licenses/ */ /* */ /* ---------------------------------------------------------------------------- */ #define DEBUGLEVEL 1 #include "iemnet.h" #include "iemnet_data.h" #include #include #include #define MAX_CONNECT 32 /* maximum number of connections */ /* ----------------------------- tcpserver ------------------------- */ static t_class *tcpserver_class; static const char objName[] = "tcpserver"; typedef struct _tcpserver_socketreceiver { struct _tcpserver *sr_owner; long sr_host; unsigned short sr_port; int sr_fd; t_iemnet_sender*sr_sender; t_iemnet_receiver*sr_receiver; } t_tcpserver_socketreceiver; typedef struct _tcpserver { t_object x_obj; t_outlet *x_msgout; t_outlet *x_connectout; t_outlet *x_sockout; // legacy t_outlet *x_addrout; // legacy t_outlet *x_statout; int x_serialize; t_tcpserver_socketreceiver *x_sr[MAX_CONNECT]; /* socket per connection */ unsigned int x_nconnections; int x_connectsocket; /* socket waiting for new connections */ int x_port; int x_defaulttarget; /* the default connection to send to; 0=broadcast; >0 use this client; <0 exclude this client */ t_iemnet_floatlist *x_floatlist; } t_tcpserver; /* forward declarations */ static void tcpserver_receive_callback(void*x, t_iemnet_chunk*); static t_tcpserver_socketreceiver *tcpserver_socketreceiver_new( t_tcpserver *owner, int sockfd, struct sockaddr_in*addr) { t_tcpserver_socketreceiver *x = (t_tcpserver_socketreceiver *)getbytes( sizeof(*x)); if(NULL==x) { iemnet_log(x, IEMNET_FATAL, "unable to allocate %d bytes", (int)sizeof(*x)); return NULL; } x->sr_owner=owner; x->sr_fd=sockfd; x->sr_host=ntohl(addr->sin_addr.s_addr); x->sr_port=ntohs(addr->sin_port); x->sr_sender=iemnet__sender_create(sockfd, NULL, NULL, 0); x->sr_receiver=iemnet__receiver_create(sockfd, x, tcpserver_receive_callback, 0); return (x); } static void tcpserver_socketreceiver_free(t_tcpserver_socketreceiver *x) { DEBUG("freeing %x", x); if (x != NULL) { int sockfd=x->sr_fd; t_iemnet_sender*sender=x->sr_sender; t_iemnet_receiver*receiver=x->sr_receiver; x->sr_owner=NULL; x->sr_sender=NULL; x->sr_receiver=NULL; x->sr_fd=-1; if(sender) { iemnet__sender_destroy(sender, 0); } if(receiver) { iemnet__receiver_destroy(receiver, 0); } iemnet__closesocket(sockfd, 1); freebytes(x, sizeof(*x)); } DEBUG("freed %x", x); } static int tcpserver_socket2index(t_tcpserver*x, int sockfd) { unsigned int i=0; for(i = 0; i < x->x_nconnections; i++) { /* check if connection exists */ if(x->x_sr[i]->sr_fd == sockfd) { return i; } } return -1; } /* checks whether client is a valid (1-based) index * if the id is invalid, returns -1 * if the id is valid, return the 0-based index (client-1) */ static int tcpserver_fixindex(t_tcpserver*x, int client) { if(x->x_nconnections <= 0) { iemnet_log(x, IEMNET_ERROR, "no clients connected"); return -1; } if (!((client > 0) && ((unsigned int)client <= x->x_nconnections))) { iemnet_log(x, IEMNET_ERROR, "client:%d out of range [1..%d]", client, (int)(x->x_nconnections)); return -1; } return (client-1); } /* ---------------- tcpserver info ---------------------------- */ static void tcpserver_info_client(t_tcpserver *x, unsigned int client) { // "client " // "bufsize " static t_atom output_atom[4]; if(x&&clientx_sr[client]) { int sockfd = x->x_sr[client]->sr_fd; unsigned short port = x->x_sr[client]->sr_port; long address = x->x_sr[client]->sr_host; char hostname[MAXPDSTRING]; int insize =iemnet__receiver_getsize(x->x_sr[client]->sr_receiver); int outsize=iemnet__sender_getsize (x->x_sr[client]->sr_sender ); snprintf(hostname, MAXPDSTRING-1, "%d.%d.%d.%d", (unsigned char)((address & 0xFF000000)>>24), (unsigned char)((address & 0x0FF0000)>>16), (unsigned char)((address & 0x0FF00)>>8), (unsigned char)((address & 0x0FF))); hostname[MAXPDSTRING-1]=0; SETFLOAT (output_atom+0, client+1); SETFLOAT (output_atom+1, sockfd); SETSYMBOL(output_atom+2, gensym(hostname)); SETFLOAT (output_atom+3, port); outlet_anything( x->x_statout, gensym("client"), 4, output_atom); SETFLOAT (output_atom+0, client+1); SETFLOAT (output_atom+1, insize); SETFLOAT (output_atom+2, outsize); outlet_anything( x->x_statout, gensym("bufsize"), 3, output_atom); } } static void tcpserver_info(t_tcpserver *x) { static t_atom output_atom[4]; int sockfd=x->x_connectsocket; int port=x->x_port; if(sockfd<0) { iemnet_log(x, IEMNET_ERROR, "no open socket"); return; } if(x->x_port<=0) { struct sockaddr_in server; socklen_t serversize=sizeof(server); if(!getsockname(sockfd, (struct sockaddr *)&server, &serversize)) { x->x_port=ntohs(server.sin_port); port=x->x_port; } else { iemnet_log(x, IEMNET_ERROR, "unable to get socket name for %d", sockfd); sys_sockerror("getsockname"); return; } } SETFLOAT (output_atom+0, port); outlet_anything( x->x_statout, gensym("port"), 1, output_atom); } static void tcpserver_info_connection(t_tcpserver *x, t_tcpserver_socketreceiver*y) { iemnet__addrout(x->x_statout, x->x_addrout, y->sr_host, y->sr_port); outlet_float(x->x_sockout, y->sr_fd); } /* ---------------- main tcpserver (send) stuff --------------------- */ static void tcpserver_disconnect_socket(t_tcpserver *x, t_floatarg fsocket); static void tcpserver_send_bytes_client(t_tcpserver*x, t_tcpserver_socketreceiver*sr, int client, t_iemnet_chunk*chunk) { if(sr) { t_atom output_atom[3]; int size=-1; t_iemnet_sender*sender=sr->sr_sender; int sockfd = sr->sr_fd; if(sender) { size=iemnet__sender_send(sender, chunk); } SETFLOAT(&output_atom[0], client+1); SETFLOAT(&output_atom[1], size); SETFLOAT(&output_atom[2], sockfd); outlet_anything( x->x_statout, gensym("sendbuffersize"), 3, output_atom); if(size<0) { // disconnected! tcpserver_disconnect_socket(x, sockfd); } } } static void tcpserver_send_bytes(t_tcpserver*x, int client, t_iemnet_chunk*chunk) { t_tcpserver_socketreceiver*sr=NULL; if(x&&clientx_sr[client]; } DEBUG("send_bytes to %p[%d] -> %p", x, client, sr); tcpserver_send_bytes_client(x, sr, client, chunk); } /* send the chunk to all non-null clients */ static void tcpserver_send_bytes_clients(t_tcpserver*x, t_tcpserver_socketreceiver**sr, unsigned int nsr, t_iemnet_chunk*chunk) { unsigned int i=0; for(i=0; ix_nconnections) { return; } chunk=iemnet__chunk_create_list(argc, argv); sr=(t_tcpserver_socketreceiver**)calloc(x->x_nconnections, sizeof(t_tcpserver_socketreceiver*)); for(client=0; clientx_nconnections; client++) { sr[client]=x->x_sr[client]; } if(butx_nconnections) { sr[but]=NULL; } tcpserver_send_bytes_clients(x, sr, x->x_nconnections, chunk); free(sr); iemnet__chunk_destroy(chunk); } /* sends a message to a given client */ static void tcpserver_send_toclient(t_tcpserver *x, unsigned int client, int argc, t_atom *argv) { t_iemnet_chunk*chunk=iemnet__chunk_create_list(argc, argv); tcpserver_send_bytes(x, client, chunk); iemnet__chunk_destroy(chunk); } /* send message to client using client number note that the client numbers might change in case a client disconnects! */ /* clients start at 1 but our index starts at 0 */ static void tcpserver_send_client(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv) { int client=0; if (argc > 0) { client=tcpserver_fixindex(x, atom_getint(argv)); if(client<0) { return; } if(argc==1) { tcpserver_info_client(x, client); } else { tcpserver_send_toclient(x, client, argc-1, argv+1); } return; } else { unsigned int client; for(client=0; clientx_nconnections; client++) { tcpserver_info_client(x, client); } } } /* broadcasts a message to all connected clients */ static void tcpserver_broadcast(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv) { unsigned int client=0; t_iemnet_chunk*chunk=NULL; t_tcpserver_socketreceiver**sr=NULL; if(!x || !x->x_nconnections) { return; } chunk=iemnet__chunk_create_list(argc, argv); sr=(t_tcpserver_socketreceiver**)calloc(x->x_nconnections, sizeof(t_tcpserver_socketreceiver*)); for(client=0; clientx_nconnections; client++) { sr[client]=x->x_sr[client]; } tcpserver_send_bytes_clients(x, sr, x->x_nconnections, chunk); free(sr); iemnet__chunk_destroy(chunk); } /* broadcasts a message to all connected clients */ static void tcpserver_broadcastbut(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv) { int but=-1; if(argc<2) { return; } if((but=tcpserver_fixindex(x, atom_getint(argv)))<0) { return; } tcpserver_send_butclient(x, but, argc-1, argv+1); } static void tcpserver_defaultsend(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv) { int client=-1; int sockfd=x->x_defaulttarget; if(sockfd>0) { client=tcpserver_socket2index(x, sockfd); if(client>=0) { tcpserver_send_toclient(x, client, argc, argv); return; } iemnet_log(x, IEMNET_ERROR, "illegal socket:%d, switching to broadcast mode", sockfd); x->x_defaulttarget=0; } else if(sockfd<0) { client=tcpserver_socket2index(x, -sockfd); if(client>=0) { tcpserver_send_butclient(x, client, argc, argv); return; } iemnet_log(x, IEMNET_ERROR, "illegal socket:%d excluded, switching to broadcast mode", sockfd); x->x_defaulttarget=0; } tcpserver_broadcast(x, s, argc, argv); } static void tcpserver_defaulttarget(t_tcpserver *x, t_floatarg f) { int sockfd=0; int rawclient=f; unsigned int client=(rawclient<0)?(-rawclient):rawclient; if(client > x->x_nconnections) { iemnet_log(x, IEMNET_ERROR, "target %d out of range [0..%d]", client, (int)(x->x_nconnections)); return; } // map the client to a persistant socket if(client>0) { sockfd=x->x_sr[client-1]->sr_fd; } if(rawclient<0) { sockfd=-sockfd; } x->x_defaulttarget=sockfd; } static void tcpserver_targetsocket(t_tcpserver *x, t_floatarg f) { int sockfd=f; x->x_defaulttarget=sockfd; } /* send message to client using socket number */ static void tcpserver_send_socket(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv) { int client = -1; t_iemnet_chunk*chunk=NULL; if(argc) { client = tcpserver_socket2index(x, atom_getint(argv)); if(client<0) { return; } } else { iemnet_log(x, IEMNET_ERROR, "no socket specified"); return; } /* get socket number of connection (first element in list) */ if(argc && argv->a_type == A_FLOAT) { int sockfd=atom_getint(argv); client = tcpserver_socket2index(x, sockfd); if(client < 0) { iemnet_log(x, IEMNET_ERROR, "no connection on socket %d", sockfd); return; } } else { iemnet_log(x, IEMNET_ERROR, "only numeric sockets allowed"); return; } chunk=iemnet__chunk_create_list(argc-1, argv+1); tcpserver_send_bytes(x, client, chunk); iemnet__chunk_destroy(chunk); } static void tcpserver_disconnect(t_tcpserver *x, unsigned int client) { unsigned int k; DEBUG("disconnect %x %d", x, client); tcpserver_info_connection(x, x->x_sr[client]); tcpserver_socketreceiver_free(x->x_sr[client]); x->x_sr[client]=NULL; /* rearrange list now: move entries to close the gap */ for(k = client; k < x->x_nconnections; k++) { x->x_sr[k] = x->x_sr[k + 1]; } x->x_sr[k + 1]=NULL; x->x_nconnections--; outlet_float(x->x_connectout, x->x_nconnections); } /* disconnect a client by number */ static void tcpserver_disconnect_client(t_tcpserver *x, t_floatarg fclient) { int client = tcpserver_fixindex(x, fclient); if(client<0) { return; } tcpserver_disconnect(x, client); } /* disconnect a client by socket */ static void tcpserver_disconnect_socket(t_tcpserver *x, t_floatarg fsocket) { int id=tcpserver_socket2index(x, (int)fsocket); if(id>=0) { tcpserver_disconnect_client(x, id+1); } } /* disconnect a client by socket */ static void tcpserver_disconnect_all(t_tcpserver *x) { unsigned int id; for(id=0; idx_nconnections; id++) { tcpserver_disconnect(x, id); } } /* ---------------- main tcpserver (receive) stuff --------------------- */ static void tcpserver_receive_callback(void *y0, t_iemnet_chunk*c) { t_tcpserver_socketreceiver *y=(t_tcpserver_socketreceiver*)y0; t_tcpserver*x=NULL; if(NULL==y || NULL==(x=y->sr_owner)) { return; } if(c) { tcpserver_info_connection(x, y); x->x_floatlist=iemnet__chunk2list(c, x->x_floatlist); // get's destroyed in the dtor iemnet__streamout(x->x_msgout, x->x_floatlist->argc, x->x_floatlist->argv, x->x_serialize); } else { // disconnected int sockfd=y->sr_fd; iemnet_log(x, IEMNET_VERBOSE, "got disconnection for socket:%d", sockfd); tcpserver_disconnect_socket(x, sockfd); } } static void tcpserver_connectpoll(t_tcpserver *x) { struct sockaddr_in incomer_address; socklen_t sockaddrl = sizeof( struct sockaddr ); int fd = accept(x->x_connectsocket, (struct sockaddr*)&incomer_address, &sockaddrl); int i; if (fd < 0) { post("%s: accept failed", objName); } else { t_tcpserver_socketreceiver *y = NULL; if(x->x_nconnections>=MAX_CONNECT) { iemnet_log(x, IEMNET_ERROR, "cannot handle more than %d connections, dropping!", x->x_nconnections); iemnet__closesocket(fd, 1); return; } y = tcpserver_socketreceiver_new((void *)x, fd, &incomer_address); if (!y) { iemnet__closesocket(fd, 1); return; } x->x_nconnections++; i = x->x_nconnections - 1; x->x_sr[i] = y; tcpserver_info_connection(x, y); } outlet_float(x->x_connectout, x->x_nconnections); } static void tcpserver_port(t_tcpserver*x, t_floatarg fportno) { static t_atom ap[1]; int portno = fportno; struct sockaddr_in server; socklen_t serversize=sizeof(server); int sockfd = x->x_connectsocket; memset(&server, 0, sizeof(server)); SETFLOAT(ap, -1); if(x->x_port == portno) { return; } /* cleanup any open ports */ if(sockfd>=0) { sys_rmpollfn(sockfd); iemnet__closesocket(sockfd, 1); x->x_connectsocket=-1; x->x_port=-1; } sockfd = socket(AF_INET, SOCK_STREAM, 0); if(sockfd<0) { iemnet_log(x, IEMNET_ERROR, "unable to create TCP/IP socket"); sys_sockerror("socket"); return; } server.sin_family = AF_INET; /* LATER allow setting of inaddr */ server.sin_addr.s_addr = INADDR_ANY; /* assign server port number */ server.sin_port = htons((u_short)portno); /* name the socket */ if (bind(sockfd, (struct sockaddr *)&server, serversize) < 0) { iemnet_log(x, IEMNET_ERROR, "unable to bind to TCP/IP socket"); sys_sockerror("bind"); iemnet__closesocket(sockfd, 1); outlet_anything(x->x_statout, gensym("port"), 1, ap); return; } /* streaming protocol */ if (listen(sockfd, 5) < 0) { iemnet_log(x, IEMNET_ERROR, "unable to listen on TCP/IP socket"); sys_sockerror("listen"); iemnet__closesocket(sockfd, 1); sockfd = -1; outlet_anything(x->x_statout, gensym("port"), 1, ap); return; } else { /* wait for new connections */ sys_addpollfn(sockfd, (t_fdpollfn)tcpserver_connectpoll, x); } x->x_connectsocket = sockfd; x->x_port = portno; // find out which port is actually used (useful when assigning "0") if(!getsockname(sockfd, (struct sockaddr *)&server, &serversize)) { x->x_port=ntohs(server.sin_port); } SETFLOAT(ap, x->x_port); outlet_anything(x->x_statout, gensym("port"), 1, ap); } static void tcpserver_serialize(t_tcpserver *x, t_floatarg doit) { x->x_serialize=doit; } static void *tcpserver_new(t_floatarg fportno) { t_tcpserver *x; int i; x = (t_tcpserver *)pd_new(tcpserver_class); x->x_msgout = outlet_new(&x->x_obj, 0); /* 1st outlet for received data */ x->x_connectout = outlet_new(&x->x_obj, gensym("float")); /* 2nd outlet for number of connected clients */ x->x_sockout = outlet_new(&x->x_obj, gensym("float")); x->x_addrout = outlet_new(&x->x_obj, gensym("list" )); x->x_statout = outlet_new(&x->x_obj, 0);/* 5th outlet for everything else */ x->x_serialize=1; x->x_connectsocket = -1; x->x_port = -1; x->x_nconnections = 0; for(i = 0; i < MAX_CONNECT; i++) { x->x_sr[i] = NULL; } x->x_defaulttarget=0; x->x_floatlist=iemnet__floatlist_create(1024); tcpserver_port(x, fportno); return (x); } static void tcpserver_free(t_tcpserver *x) { int i; for(i = 0; i < MAX_CONNECT; i++) { if (NULL!=x->x_sr[i]) { DEBUG("[%s] free %x", objName, x); tcpserver_socketreceiver_free(x->x_sr[i]); x->x_sr[i]=NULL; } } if (x->x_connectsocket >= 0) { sys_rmpollfn(x->x_connectsocket); iemnet__closesocket(x->x_connectsocket, 1); } if(x->x_floatlist) { iemnet__floatlist_destroy(x->x_floatlist); } x->x_floatlist=NULL; } IEMNET_EXTERN void tcpserver_setup(void) { if(!iemnet__register(objName)) { return; } tcpserver_class = class_new(gensym(objName),(t_newmethod)tcpserver_new, (t_method)tcpserver_free, sizeof(t_tcpserver), 0, A_DEFFLOAT, 0); class_addmethod(tcpserver_class, (t_method)tcpserver_disconnect_client, gensym("disconnectclient"), A_DEFFLOAT, 0); class_addmethod(tcpserver_class, (t_method)tcpserver_disconnect_socket, gensym("disconnectsocket"), A_DEFFLOAT, 0); class_addmethod(tcpserver_class, (t_method)tcpserver_disconnect_all, gensym("disconnect"), 0); class_addmethod(tcpserver_class, (t_method)tcpserver_send_socket, gensym("send"), A_GIMME, 0); class_addmethod(tcpserver_class, (t_method)tcpserver_send_client, gensym("client"), A_GIMME, 0); class_addmethod(tcpserver_class, (t_method)tcpserver_broadcast, gensym("broadcast"), A_GIMME, 0); class_addmethod(tcpserver_class, (t_method)tcpserver_defaulttarget, gensym("target"), A_DEFFLOAT, 0); class_addmethod(tcpserver_class, (t_method)tcpserver_targetsocket, gensym("targetsocket"), A_DEFFLOAT, 0); class_addlist (tcpserver_class, (t_method)tcpserver_defaultsend); class_addmethod(tcpserver_class, (t_method)tcpserver_serialize, gensym("serialize"), A_FLOAT, 0); class_addmethod(tcpserver_class, (t_method)tcpserver_port, gensym("port"), A_DEFFLOAT, 0); class_addbang (tcpserver_class, (t_method)tcpserver_info); DEBUGMETHOD(tcpserver_class); } IEMNET_INITIALIZER(tcpserver_setup); /* end of tcpserver.c */ pd-iemnet-0.2.1/test.txt000066400000000000000000000000271257237665700151370ustar00rootroot00000000000000testing one two three pd-iemnet-0.2.1/tests/000077500000000000000000000000001257237665700145625ustar00rootroot00000000000000pd-iemnet-0.2.1/tests/README.txt000066400000000000000000000010401257237665700162530ustar00rootroot00000000000000things that need testing ======================== all tests should be done with audio on (e.g. testtone) senders ------- - delete object - connect/disconnect - send 100MB of data -- disconnect -- delete object - send 100MB of data -- delete object receivers --------- - delete object - recv 100MB of data -- disconnect -- delete object - recv 100MB of data -- delete object data integrity -------------- repeat data back to sender (or to another receiver, for unidirectional objects) is the data consistent? (simple test: nc a large file) pd-iemnet-0.2.1/tests/bandwidth.pd000066400000000000000000000017771257237665700170670ustar00rootroot00000000000000#N canvas 5 49 777 582 10; #X obj 369 131 metro 1000; #X obj 151 249 list length; #X obj 414 203 +; #X obj 414 227 t f f; #X obj 383 256 f; #X obj 383 278 t f b; #X msg 426 279 0; #X obj 385 462 outlet bytes/sec; #X obj 385 412 makefilename %dB/s; #X obj 444 380 makefilename %dkB/s; #X obj 527 431 makefilename %dMB/s; #X obj 383 300 moses 1024; #X obj 450 328 / 1024; #X obj 449 354 moses 1024; #X obj 523 407 / 1024; #X obj 366 81 loadbang; #X obj 371 107 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 1; #X obj 151 225 inlet; #X obj 517 113 inlet length; #X connect 0 0 4 0; #X connect 1 0 2 0; #X connect 2 0 3 0; #X connect 3 0 4 1; #X connect 3 1 2 1; #X connect 4 0 5 0; #X connect 5 0 11 0; #X connect 5 1 6 0; #X connect 6 0 3 0; #X connect 8 0 7 0; #X connect 9 0 7 0; #X connect 10 0 7 0; #X connect 11 0 8 0; #X connect 11 1 12 0; #X connect 12 0 13 0; #X connect 13 0 9 0; #X connect 13 1 14 0; #X connect 14 0 10 0; #X connect 15 0 16 0; #X connect 16 0 0 0; #X connect 17 0 1 0; #X connect 18 0 2 0; pd-iemnet-0.2.1/tests/delete/000077500000000000000000000000001257237665700160245ustar00rootroot00000000000000pd-iemnet-0.2.1/tests/delete/01_send-and-delete.pd000066400000000000000000000021361257237665700216040ustar00rootroot00000000000000#N canvas 534 241 634 300 10; #X obj 332 40 udpreceive 9990; #X floatatom 332 62 5 0 0 0 - - -, f 5; #X obj 334 97 tcpreceive 9990; #X floatatom 334 119 5 0 0 0 - - -, f 5; #X obj 128 38 test-sender udpsend; #X obj 128 58 test-sender udpclient; #X obj 128 98 test-sender tcpsend; #X obj 128 118 test-sender tcpclient; #X obj 286 119 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X msg 128 16 bang; #X obj 286 40 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X obj 286 59 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X obj 286 98 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X msg 375 118 serialize 0; #X obj 450 98 loadbang; #X msg 43 45 debug \$1; #X floatatom 51 16 5 0 0 0 - - -, f 5; #X msg 286 172 \; pd quit; #X obj 286 148 select 1; #X connect 0 0 1 0; #X connect 2 0 3 0; #X connect 4 0 5 0; #X connect 4 0 10 0; #X connect 5 0 6 0; #X connect 5 0 11 0; #X connect 6 0 7 0; #X connect 6 0 12 0; #X connect 7 0 8 0; #X connect 8 0 18 0; #X connect 9 0 4 0; #X connect 13 0 2 0; #X connect 14 0 13 0; #X connect 15 0 4 0; #X connect 16 0 15 0; #X connect 18 0 17 0; pd-iemnet-0.2.1/tests/delete/test-sender.pd000066400000000000000000000724201257237665700206130ustar00rootroot00000000000000#N canvas 493 78 758 639 10; #X text 28 37 1 delete object:; #X text 32 99 2a connect; #X text 32 114 2b disconnect; #X text 32 128 2c delete; #X text 32 189 3a connect; #X text 32 204 3b delete; #X text 32 279 4a connect; #X text 32 295 4b send; #X text 32 314 4c disconnect; #X text 32 328 4d delete; #X text 32 409 5a connect; #X text 32 425 5b send; #X text 32 442 5c delete; #X msg 231 93 connect; #X msg 231 115 disconnect; #X msg 231 137 delete; #X msg 343 123 auto; #X msg 231 37 delete; #X msg 343 23 auto; #N canvas 12 50 679 407 test1 0; #X msg 101 166 connect localhost 9990; #X msg 265 166 disconnect; #X obj 25 7 inlet; #X obj 25 29 symbol; #X msg 399 219 clear; #X obj 25 51 select auto; #X obj 430 304 outlet; #X msg 538 269 0; #X obj 430 27 t b b; #X obj 430 49 t b b; #X obj 430 71 del 500; #X obj 430 93 t b b; #X obj 430 115 del 500; #X obj 430 187 t b b; #X msg 430 274 1; #N canvas 5 50 450 300 \$0-test1 0; #X obj 86 168 \$1; #X obj 86 54 inlet; #X connect 1 0 0 0; #X restore 117 345 pd \$0-test1; #X obj 99 101 select connect disconnect delete send; #N canvas 4 76 273 340 data 0; #X obj 49 35 inlet; #X obj 49 237 outlet; #N canvas 4 50 768 716 list-1024 0; #X msg 59 72 95 215 228 123 188 109 199 205 213 154 157 77 220 89 23 16 126 102 122 38 90 249 162 222 131 129 247 249 251 101 113 239 42 184 139 34 95 254 71 35 77 226 36 230 129 242 31 3 228 94 170 242 50 179 174 67 124 149 127 223 157 127 224 62 189 121 251 171 198 220 93 120 231 5 242 64 11 25 3 30 86 188 48 239 161 208 108 136 250 44 249 245 24 96 103 180 223 105 140 244 216 116 129 203 171 147 159 122 161 128 123 159 27 82 226 124 15 63 211 43 133 86 126 219 20 56 62 16 90 216 149 221 124 55 42 29 160 28 194 180 108 213 62 199 124 238 152 249 227 241 219 171 166 34 37 49 55 54 155 18 242 21 110 70 153 148 207 108 206 47 242 13 146 200 3 211 191 96 41 198 132 213 124 137 227 159 4 150 42 137 182 121 113 112 110 14 24 251 233 185 60 92 199 166 59 8 131 4 44 119 110 65 90 218 173 67 195 222 53 170 147 98 200 5 158 55 236 20 223 218 238 1 241 49 217 157 143 70 116 154 10 3 60 203 204 240 101 90 207 238 206 12 27 240 6 117 64 188 65 57 215 162 87 70 246 63 191 18 181 47 142 212 162 211 109 194 67 7 156 77 142 222 231 92 105 98 170 136 31 76 196 91 230 195 154 134 81 21 17 36 212 117 137 241 58 183 216 135 37 13 73 155 136 189 152 57 35 231 233 255 2 56 204 90 244 170 48 194 11 66 102 244 20 198 27 49 26 127 83 120 218 242 100 195 67 156 247 66 243 176 253 152 177 207 176 22 233 201 143 247 42 86 85 160 157 210 253 211 137 250 183 246 201 166 229 70 72 138 29 24 127 235 28 19 243 97 201 110 173 143 47 39 182 225 119 72 150 73 231 24 208 246 218 96 90 25 195 163 29 150 32 90 111 201 125 48 144 61 110 65 38 106 136 81 182 114 98 11 39 217 142 61 53 69 150 21 245 57 245 89 75 207 25 167 106 120 89 175 79 178 245 112 60 203 17 115 51 152 174 9 119 51 172 132 0 181 192 117 0 247 115 232 89 70 30 158 24 40 231 77 248 17 184 217 215 33 66 142 52 227 243 98 173 6 247 43 121 22 48 223 228 65 52 207 206 10 72 224 33 9 94 204 83 168 13 92 222 220 146 161 192 227 200 52 241 1 40 114 230 56 191 179 9 8 49 141 50 42 174 11 43 74 245 235 38 199 75 217 57 107 120 172 222 39 197 161 107 212 245 152 145 233 67 81 212 58 95 163 12 181 103 192 223 27 229 105 57 190 203 47 207 61 109 173 150 62 128 198 66 46 22 221 191 249 148 23 174 200 184 144 229 188 139 157 227 171 101 5 84 220 227 61 136 194 231 165 240 185 147 195 158 192 66 129 184 57 138 102 255 161 50 211 66 78 50 67 223 42 172 128 62 113 236 228 74 106 95 147 244 37 147 185 165 56 50 194 197 119 251 156 46 180 197 236 173 121 114 80 124 199 242 152 191 204 60 2 255 164 75 119 167 20 25 198 128 70 156 225 44 130 193 26 162 240 104 90 172 79 99 101 96 178 110 14 158 60 44 119 141 223 35 79 19 20 188 10 87 153 56 29 53 43 177 62 196 70 20 157 199 222 30 32 50 25 88 160 163 18 18 35 219 140 96 28 63 182 20 164 80 225 190 181 40 65 163 105 249 165 190 53 133 53 185 34 155 46 231 14 149 156 71 229 210 25 119 222 50 135 184 181 146 206 228 233 76 148 112 250 171 253 96 160 110 101 75 9 66 31 83 24 60 42 33 157 88 246 225 146 243 25 63 90 71 14 99 249 232 242 237 80 64 59 240 94 10 125 237 117 206 27 212 125 96 12 248 41 86 147 21 58 139 250 65 181 148 82 243 35 68 43 244 203 32 82 102 239 223 140 182 6 231 82 160 252 199 145 37 106 178 94 138 212 0 186 86 228 163 73 74 168 168 16 92 202 178 47 185 210 118 161 189 92 52 245 239 86 57 9 253 64 85 201 185 96 90 233 22 8 153 163 31 199 91 110 251 174 95 194 226 135 85 205 26 21 93 49 249 74 126 194 217 136 37 65 25 222 161 22 22 62 159 14 44 191 164 23 170 212 140 251 214 142 5 30 229 209 10 55 246 150 93 14 17 36 10 55 33 77 220 208 240 168 219 59 38 208 203 217 64 157 163 202 143 101 13 165 52 48 225 54 28 251 158 58 251 243 236 26 72 172 19 167 59 100 119 216 198 57 24 132 148 105 10 29 3 140 245 113 32 209 138 94 164 57; #X obj 65 28 inlet; #X obj 113 26 outlet; #X connect 0 0 2 0; #X connect 1 0 0 0; #X restore 49 179 pd list-1024; #X obj 49 150 until; #X msg 49 125 1024; #X obj 49 100 until; #X msg 49 75 1; #X connect 0 0 6 0; #X connect 2 0 1 0; #X connect 3 0 2 0; #X connect 4 0 3 0; #X connect 5 0 4 0; #X connect 6 0 5 0; #X restore 275 209 pd data; #X obj 430 140 t b b; #X obj 430 162 del 500; #X obj 397 240 s pd-\$0-test1; #X obj 249 328 r \$0-ctl; #X connect 0 0 15 0; #X connect 1 0 15 0; #X connect 2 0 3 0; #X connect 3 0 5 0; #X connect 4 0 20 0; #X connect 5 0 8 0; #X connect 5 1 16 0; #X connect 7 0 6 0; #X connect 8 0 9 0; #X connect 8 1 7 0; #X connect 9 0 10 0; #X connect 10 0 11 0; #X connect 11 0 12 0; #X connect 12 0 18 0; #X connect 13 0 14 0; #X connect 13 1 4 0; #X connect 14 0 6 0; #X connect 16 0 0 0; #X connect 16 1 1 0; #X connect 16 2 4 0; #X connect 16 3 17 0; #X connect 17 0 15 0; #X connect 18 0 19 0; #X connect 19 0 13 0; #X connect 21 0 15 0; #X restore 231 59 pd test1; #X obj 297 60 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X obj 301 160 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #N canvas 13 50 679 407 test2 0; #X msg 101 166 connect localhost 9990; #X msg 265 166 disconnect; #X obj 25 7 inlet; #X obj 25 29 symbol; #X msg 399 219 clear; #X obj 25 51 select auto; #X obj 430 304 outlet; #X msg 538 269 0; #X obj 430 27 t b b; #X obj 430 49 t b b; #X obj 430 71 del 500; #X obj 430 93 t b b; #X obj 430 115 del 500; #X obj 430 187 t b b; #X msg 430 274 1; #X obj 99 101 select connect disconnect delete send; #N canvas 4 76 273 340 data 0; #X obj 49 35 inlet; #X obj 49 237 outlet; #N canvas 4 50 768 716 list-1024 0; #X msg 59 72 95 215 228 123 188 109 199 205 213 154 157 77 220 89 23 16 126 102 122 38 90 249 162 222 131 129 247 249 251 101 113 239 42 184 139 34 95 254 71 35 77 226 36 230 129 242 31 3 228 94 170 242 50 179 174 67 124 149 127 223 157 127 224 62 189 121 251 171 198 220 93 120 231 5 242 64 11 25 3 30 86 188 48 239 161 208 108 136 250 44 249 245 24 96 103 180 223 105 140 244 216 116 129 203 171 147 159 122 161 128 123 159 27 82 226 124 15 63 211 43 133 86 126 219 20 56 62 16 90 216 149 221 124 55 42 29 160 28 194 180 108 213 62 199 124 238 152 249 227 241 219 171 166 34 37 49 55 54 155 18 242 21 110 70 153 148 207 108 206 47 242 13 146 200 3 211 191 96 41 198 132 213 124 137 227 159 4 150 42 137 182 121 113 112 110 14 24 251 233 185 60 92 199 166 59 8 131 4 44 119 110 65 90 218 173 67 195 222 53 170 147 98 200 5 158 55 236 20 223 218 238 1 241 49 217 157 143 70 116 154 10 3 60 203 204 240 101 90 207 238 206 12 27 240 6 117 64 188 65 57 215 162 87 70 246 63 191 18 181 47 142 212 162 211 109 194 67 7 156 77 142 222 231 92 105 98 170 136 31 76 196 91 230 195 154 134 81 21 17 36 212 117 137 241 58 183 216 135 37 13 73 155 136 189 152 57 35 231 233 255 2 56 204 90 244 170 48 194 11 66 102 244 20 198 27 49 26 127 83 120 218 242 100 195 67 156 247 66 243 176 253 152 177 207 176 22 233 201 143 247 42 86 85 160 157 210 253 211 137 250 183 246 201 166 229 70 72 138 29 24 127 235 28 19 243 97 201 110 173 143 47 39 182 225 119 72 150 73 231 24 208 246 218 96 90 25 195 163 29 150 32 90 111 201 125 48 144 61 110 65 38 106 136 81 182 114 98 11 39 217 142 61 53 69 150 21 245 57 245 89 75 207 25 167 106 120 89 175 79 178 245 112 60 203 17 115 51 152 174 9 119 51 172 132 0 181 192 117 0 247 115 232 89 70 30 158 24 40 231 77 248 17 184 217 215 33 66 142 52 227 243 98 173 6 247 43 121 22 48 223 228 65 52 207 206 10 72 224 33 9 94 204 83 168 13 92 222 220 146 161 192 227 200 52 241 1 40 114 230 56 191 179 9 8 49 141 50 42 174 11 43 74 245 235 38 199 75 217 57 107 120 172 222 39 197 161 107 212 245 152 145 233 67 81 212 58 95 163 12 181 103 192 223 27 229 105 57 190 203 47 207 61 109 173 150 62 128 198 66 46 22 221 191 249 148 23 174 200 184 144 229 188 139 157 227 171 101 5 84 220 227 61 136 194 231 165 240 185 147 195 158 192 66 129 184 57 138 102 255 161 50 211 66 78 50 67 223 42 172 128 62 113 236 228 74 106 95 147 244 37 147 185 165 56 50 194 197 119 251 156 46 180 197 236 173 121 114 80 124 199 242 152 191 204 60 2 255 164 75 119 167 20 25 198 128 70 156 225 44 130 193 26 162 240 104 90 172 79 99 101 96 178 110 14 158 60 44 119 141 223 35 79 19 20 188 10 87 153 56 29 53 43 177 62 196 70 20 157 199 222 30 32 50 25 88 160 163 18 18 35 219 140 96 28 63 182 20 164 80 225 190 181 40 65 163 105 249 165 190 53 133 53 185 34 155 46 231 14 149 156 71 229 210 25 119 222 50 135 184 181 146 206 228 233 76 148 112 250 171 253 96 160 110 101 75 9 66 31 83 24 60 42 33 157 88 246 225 146 243 25 63 90 71 14 99 249 232 242 237 80 64 59 240 94 10 125 237 117 206 27 212 125 96 12 248 41 86 147 21 58 139 250 65 181 148 82 243 35 68 43 244 203 32 82 102 239 223 140 182 6 231 82 160 252 199 145 37 106 178 94 138 212 0 186 86 228 163 73 74 168 168 16 92 202 178 47 185 210 118 161 189 92 52 245 239 86 57 9 253 64 85 201 185 96 90 233 22 8 153 163 31 199 91 110 251 174 95 194 226 135 85 205 26 21 93 49 249 74 126 194 217 136 37 65 25 222 161 22 22 62 159 14 44 191 164 23 170 212 140 251 214 142 5 30 229 209 10 55 246 150 93 14 17 36 10 55 33 77 220 208 240 168 219 59 38 208 203 217 64 157 163 202 143 101 13 165 52 48 225 54 28 251 158 58 251 243 236 26 72 172 19 167 59 100 119 216 198 57 24 132 148 105 10 29 3 140 245 113 32 209 138 94 164 57; #X obj 65 28 inlet; #X obj 113 26 outlet; #X connect 0 0 2 0; #X connect 1 0 0 0; #X restore 49 179 pd list-1024; #X obj 49 150 until; #X msg 49 125 1024; #X obj 49 100 until; #X msg 49 75 100; #X connect 0 0 6 0; #X connect 2 0 1 0; #X connect 3 0 2 0; #X connect 4 0 3 0; #X connect 5 0 4 0; #X connect 6 0 5 0; #X restore 275 209 pd data; #X obj 430 140 t b b; #X obj 430 162 del 500; #N canvas 4 50 450 300 \$0-test2 0; #X obj 86 168 \$1; #X obj 86 54 inlet; #X connect 1 0 0 0; #X restore 118 346 pd \$0-test2; #X obj 397 240 s pd-\$0-test2; #X obj 249 329 r \$0-ctl; #X connect 0 0 19 0; #X connect 1 0 19 0; #X connect 2 0 3 0; #X connect 3 0 5 0; #X connect 4 0 20 0; #X connect 5 0 8 0; #X connect 5 1 15 0; #X connect 7 0 6 0; #X connect 8 0 9 0; #X connect 8 1 7 0; #X connect 9 0 10 0; #X connect 9 1 0 0; #X connect 10 0 11 0; #X connect 11 0 12 0; #X connect 12 0 17 0; #X connect 13 0 14 0; #X connect 13 1 4 0; #X connect 14 0 6 0; #X connect 15 0 0 0; #X connect 15 1 1 0; #X connect 15 2 4 0; #X connect 15 3 16 0; #X connect 16 0 19 0; #X connect 17 0 18 0; #X connect 17 1 1 0; #X connect 18 0 13 0; #X connect 21 0 19 0; #X restore 231 159 pd test2; #X msg 231 193 connect; #X msg 231 217 delete; #X msg 343 203 auto; #X obj 301 240 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #N canvas 14 50 679 407 test3 0; #X msg 101 166 connect localhost 9990; #X msg 265 166 disconnect; #X obj 25 7 inlet; #X obj 25 29 symbol; #X msg 399 219 clear; #X obj 25 51 select auto; #X obj 430 304 outlet; #X msg 538 269 0; #X obj 430 27 t b b; #X obj 430 49 t b b; #X obj 430 71 del 500; #X obj 430 93 t b b; #X obj 430 115 del 500; #X obj 430 187 t b b; #X msg 430 274 1; #X obj 99 101 select connect disconnect delete send; #N canvas 4 76 273 340 data 0; #X obj 49 35 inlet; #X obj 49 237 outlet; #N canvas 4 50 768 716 list-1024 0; #X msg 59 72 95 215 228 123 188 109 199 205 213 154 157 77 220 89 23 16 126 102 122 38 90 249 162 222 131 129 247 249 251 101 113 239 42 184 139 34 95 254 71 35 77 226 36 230 129 242 31 3 228 94 170 242 50 179 174 67 124 149 127 223 157 127 224 62 189 121 251 171 198 220 93 120 231 5 242 64 11 25 3 30 86 188 48 239 161 208 108 136 250 44 249 245 24 96 103 180 223 105 140 244 216 116 129 203 171 147 159 122 161 128 123 159 27 82 226 124 15 63 211 43 133 86 126 219 20 56 62 16 90 216 149 221 124 55 42 29 160 28 194 180 108 213 62 199 124 238 152 249 227 241 219 171 166 34 37 49 55 54 155 18 242 21 110 70 153 148 207 108 206 47 242 13 146 200 3 211 191 96 41 198 132 213 124 137 227 159 4 150 42 137 182 121 113 112 110 14 24 251 233 185 60 92 199 166 59 8 131 4 44 119 110 65 90 218 173 67 195 222 53 170 147 98 200 5 158 55 236 20 223 218 238 1 241 49 217 157 143 70 116 154 10 3 60 203 204 240 101 90 207 238 206 12 27 240 6 117 64 188 65 57 215 162 87 70 246 63 191 18 181 47 142 212 162 211 109 194 67 7 156 77 142 222 231 92 105 98 170 136 31 76 196 91 230 195 154 134 81 21 17 36 212 117 137 241 58 183 216 135 37 13 73 155 136 189 152 57 35 231 233 255 2 56 204 90 244 170 48 194 11 66 102 244 20 198 27 49 26 127 83 120 218 242 100 195 67 156 247 66 243 176 253 152 177 207 176 22 233 201 143 247 42 86 85 160 157 210 253 211 137 250 183 246 201 166 229 70 72 138 29 24 127 235 28 19 243 97 201 110 173 143 47 39 182 225 119 72 150 73 231 24 208 246 218 96 90 25 195 163 29 150 32 90 111 201 125 48 144 61 110 65 38 106 136 81 182 114 98 11 39 217 142 61 53 69 150 21 245 57 245 89 75 207 25 167 106 120 89 175 79 178 245 112 60 203 17 115 51 152 174 9 119 51 172 132 0 181 192 117 0 247 115 232 89 70 30 158 24 40 231 77 248 17 184 217 215 33 66 142 52 227 243 98 173 6 247 43 121 22 48 223 228 65 52 207 206 10 72 224 33 9 94 204 83 168 13 92 222 220 146 161 192 227 200 52 241 1 40 114 230 56 191 179 9 8 49 141 50 42 174 11 43 74 245 235 38 199 75 217 57 107 120 172 222 39 197 161 107 212 245 152 145 233 67 81 212 58 95 163 12 181 103 192 223 27 229 105 57 190 203 47 207 61 109 173 150 62 128 198 66 46 22 221 191 249 148 23 174 200 184 144 229 188 139 157 227 171 101 5 84 220 227 61 136 194 231 165 240 185 147 195 158 192 66 129 184 57 138 102 255 161 50 211 66 78 50 67 223 42 172 128 62 113 236 228 74 106 95 147 244 37 147 185 165 56 50 194 197 119 251 156 46 180 197 236 173 121 114 80 124 199 242 152 191 204 60 2 255 164 75 119 167 20 25 198 128 70 156 225 44 130 193 26 162 240 104 90 172 79 99 101 96 178 110 14 158 60 44 119 141 223 35 79 19 20 188 10 87 153 56 29 53 43 177 62 196 70 20 157 199 222 30 32 50 25 88 160 163 18 18 35 219 140 96 28 63 182 20 164 80 225 190 181 40 65 163 105 249 165 190 53 133 53 185 34 155 46 231 14 149 156 71 229 210 25 119 222 50 135 184 181 146 206 228 233 76 148 112 250 171 253 96 160 110 101 75 9 66 31 83 24 60 42 33 157 88 246 225 146 243 25 63 90 71 14 99 249 232 242 237 80 64 59 240 94 10 125 237 117 206 27 212 125 96 12 248 41 86 147 21 58 139 250 65 181 148 82 243 35 68 43 244 203 32 82 102 239 223 140 182 6 231 82 160 252 199 145 37 106 178 94 138 212 0 186 86 228 163 73 74 168 168 16 92 202 178 47 185 210 118 161 189 92 52 245 239 86 57 9 253 64 85 201 185 96 90 233 22 8 153 163 31 199 91 110 251 174 95 194 226 135 85 205 26 21 93 49 249 74 126 194 217 136 37 65 25 222 161 22 22 62 159 14 44 191 164 23 170 212 140 251 214 142 5 30 229 209 10 55 246 150 93 14 17 36 10 55 33 77 220 208 240 168 219 59 38 208 203 217 64 157 163 202 143 101 13 165 52 48 225 54 28 251 158 58 251 243 236 26 72 172 19 167 59 100 119 216 198 57 24 132 148 105 10 29 3 140 245 113 32 209 138 94 164 57; #X obj 65 28 inlet; #X obj 113 26 outlet; #X connect 0 0 2 0; #X connect 1 0 0 0; #X restore 49 179 pd list-1024; #X obj 49 150 until; #X msg 49 125 1024; #X obj 49 100 until; #X msg 49 75 100; #X connect 0 0 6 0; #X connect 2 0 1 0; #X connect 3 0 2 0; #X connect 4 0 3 0; #X connect 5 0 4 0; #X connect 6 0 5 0; #X restore 275 209 pd data; #X obj 430 140 t b b; #X obj 430 162 del 500; #N canvas 4 50 450 300 \$0-test3 0; #X obj 86 168 \$1; #X obj 86 54 inlet; #X connect 1 0 0 0; #X restore 118 346 pd \$0-test3; #X obj 397 240 s pd-\$0-test3; #X obj 249 329 r \$0-ctl; #X connect 0 0 19 0; #X connect 1 0 19 0; #X connect 2 0 3 0; #X connect 3 0 5 0; #X connect 4 0 20 0; #X connect 5 0 8 0; #X connect 5 1 15 0; #X connect 7 0 6 0; #X connect 8 0 9 0; #X connect 8 1 7 0; #X connect 9 0 10 0; #X connect 9 1 0 0; #X connect 10 0 11 0; #X connect 11 0 12 0; #X connect 12 0 17 0; #X connect 13 0 14 0; #X connect 13 1 4 0; #X connect 14 0 6 0; #X connect 15 0 0 0; #X connect 15 1 1 0; #X connect 15 2 4 0; #X connect 15 3 16 0; #X connect 16 0 19 0; #X connect 17 0 18 0; #X connect 18 0 13 0; #X connect 21 0 19 0; #X restore 231 239 pd test3; #X msg 231 273 connect; #X msg 231 315 disconnect; #X msg 231 337 delete; #X msg 343 323 auto; #X obj 301 360 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X msg 231 294 send; #N canvas 12 50 679 407 test4 0; #X msg 101 166 connect localhost 9990; #X msg 265 166 disconnect; #X obj 25 7 inlet; #X obj 25 29 symbol; #X msg 399 219 clear; #X obj 25 51 select auto; #X obj 430 304 outlet; #X msg 538 269 0; #X obj 430 27 t b b; #X obj 430 49 t b b; #X obj 430 71 del 500; #X obj 430 93 t b b; #X obj 430 115 del 500; #X obj 430 187 t b b; #X msg 430 274 1; #X obj 99 101 select connect disconnect delete send; #N canvas 4 76 273 340 data 0; #X obj 49 35 inlet; #X obj 49 237 outlet; #N canvas 4 50 768 716 list-1024 0; #X msg 59 72 95 215 228 123 188 109 199 205 213 154 157 77 220 89 23 16 126 102 122 38 90 249 162 222 131 129 247 249 251 101 113 239 42 184 139 34 95 254 71 35 77 226 36 230 129 242 31 3 228 94 170 242 50 179 174 67 124 149 127 223 157 127 224 62 189 121 251 171 198 220 93 120 231 5 242 64 11 25 3 30 86 188 48 239 161 208 108 136 250 44 249 245 24 96 103 180 223 105 140 244 216 116 129 203 171 147 159 122 161 128 123 159 27 82 226 124 15 63 211 43 133 86 126 219 20 56 62 16 90 216 149 221 124 55 42 29 160 28 194 180 108 213 62 199 124 238 152 249 227 241 219 171 166 34 37 49 55 54 155 18 242 21 110 70 153 148 207 108 206 47 242 13 146 200 3 211 191 96 41 198 132 213 124 137 227 159 4 150 42 137 182 121 113 112 110 14 24 251 233 185 60 92 199 166 59 8 131 4 44 119 110 65 90 218 173 67 195 222 53 170 147 98 200 5 158 55 236 20 223 218 238 1 241 49 217 157 143 70 116 154 10 3 60 203 204 240 101 90 207 238 206 12 27 240 6 117 64 188 65 57 215 162 87 70 246 63 191 18 181 47 142 212 162 211 109 194 67 7 156 77 142 222 231 92 105 98 170 136 31 76 196 91 230 195 154 134 81 21 17 36 212 117 137 241 58 183 216 135 37 13 73 155 136 189 152 57 35 231 233 255 2 56 204 90 244 170 48 194 11 66 102 244 20 198 27 49 26 127 83 120 218 242 100 195 67 156 247 66 243 176 253 152 177 207 176 22 233 201 143 247 42 86 85 160 157 210 253 211 137 250 183 246 201 166 229 70 72 138 29 24 127 235 28 19 243 97 201 110 173 143 47 39 182 225 119 72 150 73 231 24 208 246 218 96 90 25 195 163 29 150 32 90 111 201 125 48 144 61 110 65 38 106 136 81 182 114 98 11 39 217 142 61 53 69 150 21 245 57 245 89 75 207 25 167 106 120 89 175 79 178 245 112 60 203 17 115 51 152 174 9 119 51 172 132 0 181 192 117 0 247 115 232 89 70 30 158 24 40 231 77 248 17 184 217 215 33 66 142 52 227 243 98 173 6 247 43 121 22 48 223 228 65 52 207 206 10 72 224 33 9 94 204 83 168 13 92 222 220 146 161 192 227 200 52 241 1 40 114 230 56 191 179 9 8 49 141 50 42 174 11 43 74 245 235 38 199 75 217 57 107 120 172 222 39 197 161 107 212 245 152 145 233 67 81 212 58 95 163 12 181 103 192 223 27 229 105 57 190 203 47 207 61 109 173 150 62 128 198 66 46 22 221 191 249 148 23 174 200 184 144 229 188 139 157 227 171 101 5 84 220 227 61 136 194 231 165 240 185 147 195 158 192 66 129 184 57 138 102 255 161 50 211 66 78 50 67 223 42 172 128 62 113 236 228 74 106 95 147 244 37 147 185 165 56 50 194 197 119 251 156 46 180 197 236 173 121 114 80 124 199 242 152 191 204 60 2 255 164 75 119 167 20 25 198 128 70 156 225 44 130 193 26 162 240 104 90 172 79 99 101 96 178 110 14 158 60 44 119 141 223 35 79 19 20 188 10 87 153 56 29 53 43 177 62 196 70 20 157 199 222 30 32 50 25 88 160 163 18 18 35 219 140 96 28 63 182 20 164 80 225 190 181 40 65 163 105 249 165 190 53 133 53 185 34 155 46 231 14 149 156 71 229 210 25 119 222 50 135 184 181 146 206 228 233 76 148 112 250 171 253 96 160 110 101 75 9 66 31 83 24 60 42 33 157 88 246 225 146 243 25 63 90 71 14 99 249 232 242 237 80 64 59 240 94 10 125 237 117 206 27 212 125 96 12 248 41 86 147 21 58 139 250 65 181 148 82 243 35 68 43 244 203 32 82 102 239 223 140 182 6 231 82 160 252 199 145 37 106 178 94 138 212 0 186 86 228 163 73 74 168 168 16 92 202 178 47 185 210 118 161 189 92 52 245 239 86 57 9 253 64 85 201 185 96 90 233 22 8 153 163 31 199 91 110 251 174 95 194 226 135 85 205 26 21 93 49 249 74 126 194 217 136 37 65 25 222 161 22 22 62 159 14 44 191 164 23 170 212 140 251 214 142 5 30 229 209 10 55 246 150 93 14 17 36 10 55 33 77 220 208 240 168 219 59 38 208 203 217 64 157 163 202 143 101 13 165 52 48 225 54 28 251 158 58 251 243 236 26 72 172 19 167 59 100 119 216 198 57 24 132 148 105 10 29 3 140 245 113 32 209 138 94 164 57; #X obj 65 28 inlet; #X obj 113 26 outlet; #X connect 0 0 2 0; #X connect 1 0 0 0; #X restore 49 179 pd list-1024; #X obj 49 150 until; #X msg 49 125 1024; #X obj 49 100 until; #X msg 49 75 100; #X connect 0 0 6 0; #X connect 2 0 1 0; #X connect 3 0 2 0; #X connect 4 0 3 0; #X connect 5 0 4 0; #X connect 6 0 5 0; #X restore 275 209 pd data; #X obj 430 140 t b b; #X obj 430 162 del 500; #N canvas 4 50 450 300 \$0-test4 0; #X obj 86 168 \$1; #X obj 86 54 inlet; #X connect 1 0 0 0; #X restore 118 346 pd \$0-test4; #X obj 397 240 s pd-\$0-test4; #X obj 249 329 r \$0-ctl; #X connect 0 0 19 0; #X connect 1 0 19 0; #X connect 2 0 3 0; #X connect 3 0 5 0; #X connect 4 0 20 0; #X connect 5 0 8 0; #X connect 5 1 15 0; #X connect 7 0 6 0; #X connect 8 0 9 0; #X connect 8 1 7 0; #X connect 9 0 10 0; #X connect 9 1 0 0; #X connect 10 0 11 0; #X connect 11 0 12 0; #X connect 11 1 16 0; #X connect 12 0 17 0; #X connect 13 0 14 0; #X connect 13 1 4 0; #X connect 14 0 6 0; #X connect 15 0 0 0; #X connect 15 1 1 0; #X connect 15 2 4 0; #X connect 15 3 16 0; #X connect 16 0 19 0; #X connect 17 0 18 0; #X connect 17 1 1 0; #X connect 18 0 13 0; #X connect 21 0 19 0; #X restore 231 359 pd test4; #X msg 231 403 connect; #X msg 231 467 delete; #X msg 343 453 auto; #X obj 301 490 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X msg 231 424 send; #N canvas 15 50 679 407 test5 0; #X msg 101 166 connect localhost 9990; #X msg 265 166 disconnect; #X obj 25 7 inlet; #X obj 25 29 symbol; #X msg 399 219 clear; #X obj 25 51 select auto; #X obj 430 304 outlet; #X msg 538 269 0; #X obj 430 27 t b b; #X obj 430 49 t b b; #X obj 430 71 del 500; #X obj 430 93 t b b; #X obj 430 115 del 500; #X obj 430 187 t b b; #X msg 430 274 1; #X obj 99 101 select connect disconnect delete send; #N canvas 4 76 273 340 data 0; #X obj 49 35 inlet; #X obj 49 237 outlet; #N canvas 4 50 768 716 list-1024 0; #X msg 59 72 95 215 228 123 188 109 199 205 213 154 157 77 220 89 23 16 126 102 122 38 90 249 162 222 131 129 247 249 251 101 113 239 42 184 139 34 95 254 71 35 77 226 36 230 129 242 31 3 228 94 170 242 50 179 174 67 124 149 127 223 157 127 224 62 189 121 251 171 198 220 93 120 231 5 242 64 11 25 3 30 86 188 48 239 161 208 108 136 250 44 249 245 24 96 103 180 223 105 140 244 216 116 129 203 171 147 159 122 161 128 123 159 27 82 226 124 15 63 211 43 133 86 126 219 20 56 62 16 90 216 149 221 124 55 42 29 160 28 194 180 108 213 62 199 124 238 152 249 227 241 219 171 166 34 37 49 55 54 155 18 242 21 110 70 153 148 207 108 206 47 242 13 146 200 3 211 191 96 41 198 132 213 124 137 227 159 4 150 42 137 182 121 113 112 110 14 24 251 233 185 60 92 199 166 59 8 131 4 44 119 110 65 90 218 173 67 195 222 53 170 147 98 200 5 158 55 236 20 223 218 238 1 241 49 217 157 143 70 116 154 10 3 60 203 204 240 101 90 207 238 206 12 27 240 6 117 64 188 65 57 215 162 87 70 246 63 191 18 181 47 142 212 162 211 109 194 67 7 156 77 142 222 231 92 105 98 170 136 31 76 196 91 230 195 154 134 81 21 17 36 212 117 137 241 58 183 216 135 37 13 73 155 136 189 152 57 35 231 233 255 2 56 204 90 244 170 48 194 11 66 102 244 20 198 27 49 26 127 83 120 218 242 100 195 67 156 247 66 243 176 253 152 177 207 176 22 233 201 143 247 42 86 85 160 157 210 253 211 137 250 183 246 201 166 229 70 72 138 29 24 127 235 28 19 243 97 201 110 173 143 47 39 182 225 119 72 150 73 231 24 208 246 218 96 90 25 195 163 29 150 32 90 111 201 125 48 144 61 110 65 38 106 136 81 182 114 98 11 39 217 142 61 53 69 150 21 245 57 245 89 75 207 25 167 106 120 89 175 79 178 245 112 60 203 17 115 51 152 174 9 119 51 172 132 0 181 192 117 0 247 115 232 89 70 30 158 24 40 231 77 248 17 184 217 215 33 66 142 52 227 243 98 173 6 247 43 121 22 48 223 228 65 52 207 206 10 72 224 33 9 94 204 83 168 13 92 222 220 146 161 192 227 200 52 241 1 40 114 230 56 191 179 9 8 49 141 50 42 174 11 43 74 245 235 38 199 75 217 57 107 120 172 222 39 197 161 107 212 245 152 145 233 67 81 212 58 95 163 12 181 103 192 223 27 229 105 57 190 203 47 207 61 109 173 150 62 128 198 66 46 22 221 191 249 148 23 174 200 184 144 229 188 139 157 227 171 101 5 84 220 227 61 136 194 231 165 240 185 147 195 158 192 66 129 184 57 138 102 255 161 50 211 66 78 50 67 223 42 172 128 62 113 236 228 74 106 95 147 244 37 147 185 165 56 50 194 197 119 251 156 46 180 197 236 173 121 114 80 124 199 242 152 191 204 60 2 255 164 75 119 167 20 25 198 128 70 156 225 44 130 193 26 162 240 104 90 172 79 99 101 96 178 110 14 158 60 44 119 141 223 35 79 19 20 188 10 87 153 56 29 53 43 177 62 196 70 20 157 199 222 30 32 50 25 88 160 163 18 18 35 219 140 96 28 63 182 20 164 80 225 190 181 40 65 163 105 249 165 190 53 133 53 185 34 155 46 231 14 149 156 71 229 210 25 119 222 50 135 184 181 146 206 228 233 76 148 112 250 171 253 96 160 110 101 75 9 66 31 83 24 60 42 33 157 88 246 225 146 243 25 63 90 71 14 99 249 232 242 237 80 64 59 240 94 10 125 237 117 206 27 212 125 96 12 248 41 86 147 21 58 139 250 65 181 148 82 243 35 68 43 244 203 32 82 102 239 223 140 182 6 231 82 160 252 199 145 37 106 178 94 138 212 0 186 86 228 163 73 74 168 168 16 92 202 178 47 185 210 118 161 189 92 52 245 239 86 57 9 253 64 85 201 185 96 90 233 22 8 153 163 31 199 91 110 251 174 95 194 226 135 85 205 26 21 93 49 249 74 126 194 217 136 37 65 25 222 161 22 22 62 159 14 44 191 164 23 170 212 140 251 214 142 5 30 229 209 10 55 246 150 93 14 17 36 10 55 33 77 220 208 240 168 219 59 38 208 203 217 64 157 163 202 143 101 13 165 52 48 225 54 28 251 158 58 251 243 236 26 72 172 19 167 59 100 119 216 198 57 24 132 148 105 10 29 3 140 245 113 32 209 138 94 164 57; #X obj 65 28 inlet; #X obj 113 26 outlet; #X connect 0 0 2 0; #X connect 1 0 0 0; #X restore 49 179 pd list-1024; #X obj 49 150 until; #X msg 49 125 1024; #X obj 49 100 until; #X msg 49 75 100; #X connect 0 0 6 0; #X connect 2 0 1 0; #X connect 3 0 2 0; #X connect 4 0 3 0; #X connect 5 0 4 0; #X connect 6 0 5 0; #X restore 275 209 pd data; #X obj 430 140 t b b; #X obj 430 162 del 500; #N canvas 5 50 450 300 \$0-test5 0; #X obj 86 168 \$1; #X obj 86 54 inlet; #X connect 1 0 0 0; #X restore 118 346 pd \$0-test5; #X obj 397 240 s pd-\$0-test5; #X obj 249 329 r \$0-ctl; #X connect 0 0 19 0; #X connect 1 0 19 0; #X connect 2 0 3 0; #X connect 3 0 5 0; #X connect 4 0 20 0; #X connect 5 0 8 0; #X connect 5 1 15 0; #X connect 7 0 6 0; #X connect 8 0 9 0; #X connect 8 1 7 0; #X connect 9 0 10 0; #X connect 9 1 0 0; #X connect 10 0 11 0; #X connect 11 0 12 0; #X connect 11 1 16 0; #X connect 12 0 17 0; #X connect 13 0 14 0; #X connect 13 1 4 0; #X connect 14 0 6 0; #X connect 15 0 0 0; #X connect 15 1 1 0; #X connect 15 2 4 0; #X connect 15 3 16 0; #X connect 16 0 19 0; #X connect 17 0 18 0; #X connect 18 0 13 0; #X connect 21 0 19 0; #X restore 231 490 pd test5; #X obj 522 15 inlet; #X obj 343 58 spigot 0; #X obj 406 58 r \$0-auto; #X obj 343 80 select 1; #X obj 343 158 spigot 0; #X obj 406 158 r \$0-auto; #X obj 343 180 select 1; #X obj 343 238 spigot 0; #X obj 406 238 r \$0-auto; #X obj 343 260 select 1; #X obj 343 358 spigot 0; #X obj 406 358 r \$0-auto; #X obj 343 380 select 1; #X obj 343 508 spigot 0; #X obj 406 508 r \$0-auto; #X obj 343 530 select 1; #X obj 596 82 t b b; #X msg 628 105 1; #X obj 628 127 s \$0-auto; #X obj 343 552 t b b; #X msg 413 549 0; #X obj 413 571 s \$0-auto; #X obj 522 524 r \$0-auto; #X obj 522 546 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X msg 343 574 1; #X obj 343 596 outlet; #X obj 522 37 route debug; #X obj 522 81 s \$0-ctl; #X msg 522 59 debug \$1; #X connect 13 0 22 0; #X connect 14 0 22 0; #X connect 15 0 22 0; #X connect 16 0 22 0; #X connect 17 0 19 0; #X connect 18 0 19 0; #X connect 19 0 20 0; #X connect 20 0 42 0; #X connect 21 0 45 0; #X connect 22 0 21 0; #X connect 23 0 27 0; #X connect 24 0 27 0; #X connect 25 0 27 0; #X connect 26 0 48 0; #X connect 27 0 26 0; #X connect 28 0 34 0; #X connect 29 0 34 0; #X connect 30 0 34 0; #X connect 31 0 34 0; #X connect 32 0 51 0; #X connect 33 0 34 0; #X connect 34 0 32 0; #X connect 35 0 40 0; #X connect 36 0 40 0; #X connect 37 0 40 0; #X connect 38 0 54 0; #X connect 39 0 40 0; #X connect 40 0 38 0; #X connect 41 0 67 0; #X connect 42 0 44 0; #X connect 43 0 42 1; #X connect 44 0 16 0; #X connect 45 0 47 0; #X connect 46 0 45 1; #X connect 47 0 25 0; #X connect 48 0 50 0; #X connect 49 0 48 1; #X connect 50 0 31 0; #X connect 51 0 53 0; #X connect 52 0 51 1; #X connect 53 0 37 0; #X connect 54 0 56 0; #X connect 55 0 54 1; #X connect 56 0 60 0; #X connect 57 0 18 0; #X connect 57 1 58 0; #X connect 58 0 59 0; #X connect 60 0 65 0; #X connect 60 1 61 0; #X connect 61 0 62 0; #X connect 63 0 64 0; #X connect 65 0 66 0; #X connect 67 0 69 0; #X connect 67 1 57 0; #X connect 69 0 68 0; pd-iemnet-0.2.1/tests/packetgenerator.pd000066400000000000000000000025731257237665700202740ustar00rootroot00000000000000#N canvas 139 114 832 501 10; #X obj 94 27 inlet on/off; #X obj 94 119 metro 100; #X obj 94 336 outlet data; #X obj 252 29 inlet packetsize; #N canvas 9 49 701 343 makepacket 0; #X obj 120 19 inlet value; #X obj 328 22 inlet length; #X obj 328 44 i 10; #X obj 421 21 loadbang; #X obj 328 66 t f b; #X obj 328 88 until; #X msg 120 170 list; #X msg 328 110 adddollar 1; #X obj 70 290 outlet; #X floatatom 391 54 5 0 0 0 - - -; #X msg 419 112 set list; #X connect 0 0 6 0; #X connect 1 0 2 0; #X connect 2 0 4 0; #X connect 3 0 2 0; #X connect 4 0 5 0; #X connect 4 1 10 0; #X connect 5 0 7 0; #X connect 6 0 8 0; #X connect 7 0 6 0; #X connect 9 0 2 0; #X connect 10 0 6 0; #X restore 94 191 pd makepacket; #N canvas 6 49 450 300 count 0; #X obj 106 68 i; #X obj 106 110 + 1; #X obj 106 90 % 255; #X obj 106 132 t f f; #X obj 106 36 inlet; #X obj 106 154 outlet; #X obj 198 33 inlet value; #X connect 0 0 2 0; #X connect 1 0 3 0; #X connect 2 0 1 0; #X connect 3 0 5 0; #X connect 3 1 0 1; #X connect 4 0 0 0; #X connect 6 0 0 1; #X restore 94 168 pd count 1..255; #X obj 94 89 t f f; #X obj 94 213 t l l; #X obj 504 32 inlet rate; #X obj 95 49 route float bang; #X obj 177 124 t b; #X connect 0 0 9 0; #X connect 1 0 5 0; #X connect 3 0 4 1; #X connect 4 0 7 0; #X connect 5 0 4 0; #X connect 6 0 1 0; #X connect 7 0 2 0; #X connect 8 0 1 1; #X connect 9 0 6 0; #X connect 9 1 10 0; #X connect 10 0 5 0; pd-iemnet-0.2.1/tests/reconnect/000077500000000000000000000000001257237665700165425ustar00rootroot00000000000000pd-iemnet-0.2.1/tests/reconnect/01_reconnect-crash.pd000066400000000000000000000014751257237665700224540ustar00rootroot00000000000000#N canvas 243 49 699 424 10; #X msg 22 255 disconnect; #X msg 112 177 connect localhost 44100; #X obj 21 344 tcpserver 44100; #X obj 22 322 tcpclient; #X obj 22 149 t b b b; #X obj 22 70 tgl 15 0 empty empty empty 17 7 0 10 -261234 -1 -1 1 1 ; #X msg 106 248 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 255; #X obj 106 219 del 20; #X obj 22 231 del 40; #X obj 22 110 metro 60; #X text 78 68 This patch appears to crash Pd after a few cycles of disconnect|send|reconnect.; #X text 44 71 <-; #X floatatom 68 378 5 0 0 0 - - -; #X msg 217 349 64 64 64; #X connect 0 0 3 0; #X connect 1 0 3 0; #X connect 2 1 12 0; #X connect 4 0 8 0; #X connect 4 1 7 0; #X connect 4 2 1 0; #X connect 5 0 9 0; #X connect 6 0 3 0; #X connect 7 0 6 0; #X connect 8 0 0 0; #X connect 9 0 4 0; #X connect 13 0 2 0; pd-iemnet-0.2.1/tests/reconnect/04_reconnect-dropped-byte-2-client.pd000066400000000000000000000040321257237665700253600ustar00rootroot00000000000000#N canvas 2026 49 530 584 10; #X msg 5 222 disconnect; #X msg 46 107 connect localhost 44100; #X obj 46 285 tcpclient; #X obj 148 391 list prepend; #X obj 46 322 sel 255; #X obj 85 429 list append; #X obj 165 469 list length; #X obj 85 468 t a a; #X obj 165 491 sel 30; #X obj 198 566 print ERROR; #X msg 198 545 byte count wrong: \$1 bytes; #X obj 46 81 metro 1000; #X obj 46 344 t b b b; #X obj 46 34 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1 ; #X floatatom 135 47 5 0 0 0 - - -; #X obj 46 262 t a a; #X msg 399 44 bang; #X obj 399 64 print foo; #X obj 340 429 i; #X obj 340 449 + 1; #X obj 340 469 t f f; #X floatatom 340 489 5 0 0 0 - - -; #X obj 317 56 metro 1000; #X obj 317 76 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 317 33 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X msg 137 25 10; #X floatatom 78 181 5 0 0 0 - - -; #X obj 78 220 payload; #X obj 198 519 t f b b; #X msg 256 516 0; #X obj 135 64 t f f; #X obj 176 80 print timmms; #X obj 46 305 t a a; #X obj 78 200 sel 1 0; #X obj 148 410 t a a; #X obj 86 262 sprint TCPCLIENT; #X obj 89 304 sprint CLIENTrec; #X obj 85 526 sprint packet 1; #X connect 0 0 15 0; #X connect 1 0 15 0; #X connect 2 0 32 0; #X connect 2 2 26 0; #X connect 3 0 34 0; #X connect 4 0 12 0; #X connect 4 1 3 0; #X connect 5 0 7 0; #X connect 6 0 8 0; #X connect 7 0 37 0; #X connect 7 1 6 0; #X connect 8 1 28 0; #X connect 10 0 9 0; #X connect 11 0 1 0; #X connect 12 0 0 0; #X connect 12 1 5 1; #X connect 12 1 3 1; #X connect 12 2 5 0; #X connect 13 0 11 0; #X connect 14 0 30 0; #X connect 15 0 2 0; #X connect 15 1 35 0; #X connect 16 0 17 0; #X connect 18 0 19 0; #X connect 19 0 20 0; #X connect 20 0 21 0; #X connect 20 1 18 1; #X connect 22 0 23 0; #X connect 24 0 22 0; #X connect 25 0 14 0; #X connect 26 0 33 0; #X connect 27 0 15 0; #X connect 28 0 10 0; #X connect 28 1 18 0; #X connect 28 2 29 0; #X connect 30 0 11 1; #X connect 30 1 31 0; #X connect 32 0 4 0; #X connect 32 1 36 0; #X connect 33 0 27 0; #X connect 33 1 34 0; #X connect 34 0 5 1; #X connect 34 1 3 1; pd-iemnet-0.2.1/tests/reconnect/04_reconnect-dropped-byte-2-server.pd000066400000000000000000000006611257237665700254140ustar00rootroot00000000000000#N canvas 1298 426 599 289 10; #X obj 77 93 list prepend broadcast; #X obj 77 115 list trim; #X obj 77 36 tcpserver 44100; #X obj 19 53 t a a a; #X obj 77 56 t a a a; #X obj 212 169 select 255; #X obj 212 189 sprint =======================; #X obj 126 56 sprint TCPSERVER; #X connect 0 0 1 0; #X connect 1 0 3 0; #X connect 2 0 4 0; #X connect 3 1 2 0; #X connect 4 0 5 0; #X connect 4 1 0 0; #X connect 4 2 7 0; #X connect 5 0 6 0; pd-iemnet-0.2.1/tests/reconnect/payload.pd000066400000000000000000000003351257237665700205210ustar00rootroot00000000000000#N canvas 4 49 450 300 10; #X obj 135 52 inlet bang; #X obj 142 256 outlet data; #X msg 86 140 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 255; #X connect 0 0 2 0; #X connect 2 0 1 0; pd-iemnet-0.2.1/tests/reconnect/reconnect-dropped-byte.pd000066400000000000000000000025721257237665700234510ustar00rootroot00000000000000#N canvas 242 49 530 584 10; #X msg 23 208 disconnect; #X msg 113 130 connect localhost 44100; #X obj 335 71 list prepend broadcast; #X obj 335 93 list trim; #X obj 298 62 t a; #X obj 335 44 tcpserver 44100; #X obj 46 285 tcpclient; #X obj 23 102 t b b b; #X obj 107 172 del 30; #X obj 23 184 del 60; #X obj 23 63 metro 100; #X obj 23 23 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1 ; #X obj 136 374 list prepend; #X obj 231 374 t a; #X obj 46 322 sel 255; #X obj 73 399 list append; #X obj 46 344 t b b; #X obj 153 452 list length; #X obj 73 421 t a a; #X obj 153 474 sel 30; #X obj 186 519 print ERROR; #X msg 107 201 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 255; #X obj 73 509 print packet; #X msg 186 498 byte count wrong: \$1 bytes; #X connect 0 0 6 0; #X connect 1 0 6 0; #X connect 2 0 3 0; #X connect 3 0 4 0; #X connect 4 0 5 0; #X connect 5 0 2 0; #X connect 6 0 14 0; #X connect 7 0 9 0; #X connect 7 1 8 0; #X connect 7 2 1 0; #X connect 8 0 21 0; #X connect 9 0 0 0; #X connect 10 0 7 0; #X connect 11 0 10 0; #X connect 12 0 13 0; #X connect 12 0 15 1; #X connect 13 0 12 1; #X connect 14 0 16 0; #X connect 14 1 12 0; #X connect 15 0 18 0; #X connect 16 0 15 1; #X connect 16 0 12 1; #X connect 16 1 15 0; #X connect 17 0 19 0; #X connect 18 0 22 0; #X connect 18 1 17 0; #X connect 19 1 23 0; #X connect 21 0 6 0; #X connect 23 0 20 0; pd-iemnet-0.2.1/tests/reconnect/serialize.pd000066400000000000000000000005561257237665700210640ustar00rootroot00000000000000#N canvas 4 49 450 300 10; #X obj 63 190 list split 1; #X obj 63 107 until; #X obj 63 145 list append; #X obj 89 74 t b l; #X obj 193 190 bang; #X obj 63 210 outlet; #X obj 99 45 inlet; #X connect 0 0 5 0; #X connect 0 1 2 1; #X connect 0 2 4 0; #X connect 1 0 2 0; #X connect 2 0 0 0; #X connect 3 0 1 0; #X connect 3 1 2 1; #X connect 4 0 1 1; #X connect 6 0 3 0; pd-iemnet-0.2.1/tests/reconnect/sprint.pd000066400000000000000000000010001257237665700203750ustar00rootroot00000000000000#N canvas 4 49 450 300 10; #X obj 74 144 spigot; #X obj 100 100 tgl 15 0 \$0-spigot \$0-spigot empty 17 7 0 10 -262144 -1 -1 0 1; #X obj 141 134 r \$0-spigot; #X obj 74 53 inlet; #X obj 74 164 print \$1; #X obj 227 37 loadbang; #X obj 227 57 list prepend \$2; #X obj 227 77 route float; #X obj 227 97 s \$0-spigot; #X obj 354 31 inlet; #X connect 0 0 4 0; #X connect 2 0 0 1; #X connect 3 0 0 0; #X connect 5 0 6 0; #X connect 6 0 7 0; #X connect 7 0 8 0; #X connect 9 0 7 0; #X coords 0 -1 1 1 15 15 1 100 100; pd-iemnet-0.2.1/tests/reflect/000077500000000000000000000000001257237665700162065ustar00rootroot00000000000000pd-iemnet-0.2.1/tests/reflect/01_tcp.pd000066400000000000000000000010231257237665700176150ustar00rootroot00000000000000#N canvas 1583 339 487 300 10; #X obj 54 183 spigot; #X obj 54 227 t f f; #X obj 54 249 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 1; #X msg 120 184 disconnect \, connect localhost 9998; #X text 44 26 this sends all data received on TCP:9999 back on TCP:9998 ; #X obj 120 158 loadbang; #X obj 54 112 tcpreceive 9999; #X obj 54 205 tcpsend; #X obj 54 134 t a a; #X connect 0 0 7 0; #X connect 1 0 2 0; #X connect 1 1 0 1; #X connect 3 0 7 0; #X connect 5 0 3 0; #X connect 6 0 8 0; #X connect 7 0 1 0; #X connect 8 0 0 0; pd-iemnet-0.2.1/tests/reflect/02_udp.pd000066400000000000000000000007511257237665700176270ustar00rootroot00000000000000#N canvas 341 348 487 300 10; #X obj 54 112 udpreceive 9999; #X obj 54 205 udpsend; #X obj 54 183 spigot; #X obj 54 227 t f f; #X obj 54 249 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X msg 120 184 disconnect \, connect localhost 9998; #X text 44 26 this sends all data received on UDP:9999 back on UDP:9998 ; #X obj 120 158 loadbang; #X connect 0 0 2 0; #X connect 1 0 3 0; #X connect 2 0 1 0; #X connect 3 0 4 0; #X connect 3 1 2 1; #X connect 5 0 1 0; #X connect 7 0 5 0; pd-iemnet-0.2.1/tests/reflect/03_tcpserver.pd000066400000000000000000000031241257237665700210520ustar00rootroot00000000000000#N canvas 148 388 826 376 10; #X obj 116 59 tcpserver 9999; #X obj 28 66 t a a; #X msg 144 26 serialize 0; #X text 376 126 OLD=0.077s (+dropout); #X text 45 199 zmoelnig/rtsp.log (37M); #X text 43 173 YoYoTheMovie_comp.mov; #X text 375 158 OLD=0.735 (+dropouts); #X text 35 225 zmoelnig/Hydro...wav (223M); #X text 379 140 NEW=0.104s (+dropout); #X text 374 169 NEW=0.812 (+dropouts); #X text 382 206 NEW=9.880 (+dropouts \, NOfreeze); #X text 377 188 OLD=9.341 (+dropouts \, NOfreeze); #X text 443 98 reflect; #X text 637 95 receive-only; #X text 641 165 0.67 (+dropouts); #X text 641 136 0.064 (+dropouts); #X text 632 198 3.672(+dropouts); #X text 632 185 3.672(+fewdropouts); #X text 634 213 MRPEACH:4.8(NOdrops); #X obj 31 125 list prepend broadcast; #X obj 31 147 list trim; #X obj 245 64 list length; #X obj 245 86 +; #X obj 245 108 t f f; #X obj 229 128 f; #X obj 258 33 t b b; #X msg 277 88 0; #X floatatom 229 150 0 0 0 0 - - -; #X msg 254 8 bang; #X floatatom 229 223 0 0 0 0 - - -; #X msg 259 130 bang; #X obj 229 172 / 1000; #X obj 229 194 int; #X obj 286 174 % 1000; #X floatatom 286 196 5 0 0 0 - - -, f 5; #X msg 205 106 bang; #X connect 0 0 1 0; #X connect 1 0 19 0; #X connect 1 1 21 0; #X connect 2 0 0 0; #X connect 19 0 20 0; #X connect 20 0 0 0; #X connect 21 0 22 0; #X connect 22 0 23 0; #X connect 23 0 24 1; #X connect 23 1 22 1; #X connect 24 0 27 0; #X connect 25 0 26 0; #X connect 25 1 24 0; #X connect 26 0 23 0; #X connect 27 0 31 0; #X connect 27 0 33 0; #X connect 28 0 25 0; #X connect 30 0 27 0; #X connect 31 0 32 0; #X connect 32 0 29 0; #X connect 33 0 34 0; #X connect 35 0 24 0; pd-iemnet-0.2.1/tests/sequence/000077500000000000000000000000001257237665700163725ustar00rootroot00000000000000pd-iemnet-0.2.1/tests/sequence/01_client.pd000066400000000000000000000054131257237665700205000ustar00rootroot00000000000000#N canvas 501 150 636 624 10; #X obj 139 179 tcpclient; #X msg 308 152 connect \$1 9999; #X msg 308 108 bang; #X obj 308 130 symbol localhost; #X symbolatom 351 112 10 0 0 0 - - -; #X obj 159 201 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 127 127; #X obj 139 284 list split 1; #X obj 139 242 until; #X obj 139 263 list append; #X obj 139 219 t b l; #X obj 183 243 bang; #X obj 139 306 select 255; #X obj 139 328 i; #X obj 139 350 + 1; #X obj 139 372 t f f; #X obj 121 398 f; #X obj 114 108 metro 100; #X obj 114 85 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X msg 114 130 1; #X obj 79 323 t b b; #X msg 108 345 0; #X floatatom 121 555 5 0 0 3 dummyload - -; #X obj 253 378 -; #X obj 252 354 t f f; #X obj 253 400 select 1; #X obj 306 489 print error; #X obj 306 443 pack 0 0 0; #X obj 185 426 t f f; #X obj 373 416 + 1; #X obj 185 448 select 254; #X msg 185 470 -1; #X obj 206 328 t b f f f; #X msg 306 465 \$2 should be \$3; #X obj 306 421 t b b; #X obj 459 485 i; #X obj 459 507 + 1; #X obj 459 529 t f f; #X floatatom 459 551 5 0 0 3 errors - -; #X text 49 27 testing the server; #X floatatom 188 78 5 0 0 0 - - -; #X obj 55 394 i; #X obj 55 416 + 1; #X obj 55 438 t f f; #X floatatom 22 481 5 0 0 3 iterations - -; #X msg 56 372 0; #X obj 52 125 t b b; #X obj 52 147 timer; #X floatatom 52 169 5 0 0 0 - - -; #X obj 22 458 i; #X obj 14 344 metro 100; #X msg 14 366 bang; #X obj 16 325 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X connect 0 0 9 0; #X connect 0 1 5 0; #X connect 1 0 0 0; #X connect 2 0 3 0; #X connect 3 0 1 0; #X connect 4 0 3 0; #X connect 6 0 11 0; #X connect 6 1 8 1; #X connect 6 2 10 0; #X connect 7 0 8 0; #X connect 8 0 6 0; #X connect 9 0 7 0; #X connect 9 1 8 1; #X connect 10 0 7 1; #X connect 11 0 12 0; #X connect 11 1 31 0; #X connect 12 0 13 0; #X connect 13 0 14 0; #X connect 14 0 15 1; #X connect 14 1 12 1; #X connect 15 0 21 0; #X connect 16 0 18 0; #X connect 16 0 45 0; #X connect 17 0 16 0; #X connect 18 0 0 0; #X connect 19 0 15 0; #X connect 19 1 20 0; #X connect 19 1 40 0; #X connect 20 0 12 1; #X connect 22 0 24 0; #X connect 23 0 22 1; #X connect 23 1 22 0; #X connect 24 1 33 0; #X connect 26 0 32 0; #X connect 27 0 29 0; #X connect 27 1 28 0; #X connect 28 0 26 2; #X connect 29 0 30 0; #X connect 30 0 22 1; #X connect 31 0 19 0; #X connect 31 1 27 0; #X connect 31 2 23 0; #X connect 31 3 26 1; #X connect 32 0 25 0; #X connect 33 0 26 0; #X connect 33 1 34 0; #X connect 34 0 35 0; #X connect 35 0 36 0; #X connect 36 0 37 0; #X connect 36 1 34 1; #X connect 39 0 16 1; #X connect 40 0 41 0; #X connect 41 0 42 0; #X connect 42 0 48 1; #X connect 42 1 40 1; #X connect 44 0 40 0; #X connect 45 0 46 0; #X connect 45 1 46 1; #X connect 46 0 47 0; #X connect 48 0 43 0; #X connect 49 0 50 0; #X connect 50 0 48 0; #X connect 51 0 49 0; pd-iemnet-0.2.1/tests/sequence/01_server.pd000066400000000000000000000027601257237665700205320ustar00rootroot00000000000000#N canvas 219 165 438 532 10; #X obj 71 256 tcpserver 9999; #X obj 71 278 t b; #X obj 71 300 i; #X obj 115 326 + 1; #X obj 115 348 % 255; #X obj 250 252 loadbang; #X msg 71 388 broadcast \$1; #X obj 71 429 list append; #X obj 250 274 f 1024; #X obj 250 296 t b f b; #X obj 250 438 list prepend; #X obj 273 319 until; #X obj 273 341 f 255; #X obj 273 363 list prepend; #X obj 273 385 t l l; #X msg 106 276 bang; #X msg 321 250 bang; #X obj 71 451 list trim; #X obj 23 229 t a; #X text 27 43 responds to any data from the client by sending pack a stream consisting of a header and a dummy payload.; #X text 31 84 the dummy payload is a number of 0xFF bytes; #X obj 71 322 t f f; #X text 32 99 the header is a single byte counting up from 0..254 (and wrapping around); #X floatatom 166 305 5 0 0 0 - - -; #X obj 152 169 route sent; #X obj 152 191 unpack 0 0 0; #X floatatom 186 225 0 0 0 0 - - -; #X floatatom 221 211 5 0 0 0 - - -; #X connect 0 0 1 0; #X connect 0 4 24 0; #X connect 1 0 2 0; #X connect 2 0 21 0; #X connect 3 0 4 0; #X connect 4 0 2 1; #X connect 5 0 8 0; #X connect 6 0 7 0; #X connect 7 0 17 0; #X connect 8 0 9 0; #X connect 9 0 10 0; #X connect 9 1 11 0; #X connect 10 0 7 1; #X connect 11 0 12 0; #X connect 12 0 13 0; #X connect 13 0 14 0; #X connect 14 0 10 1; #X connect 14 1 13 1; #X connect 15 0 1 0; #X connect 16 0 8 0; #X connect 17 0 18 0; #X connect 18 0 0 0; #X connect 21 0 6 0; #X connect 21 1 3 0; #X connect 23 0 3 1; #X connect 24 0 25 0; #X connect 25 1 26 0; #X connect 25 2 27 0; pd-iemnet-0.2.1/tests/sequence/01_tcpclient.pd000066400000000000000000000054131257237665700212070ustar00rootroot00000000000000#N canvas 501 150 636 624 10; #X obj 139 179 tcpclient; #X msg 308 152 connect \$1 9999; #X msg 308 108 bang; #X obj 308 130 symbol localhost; #X symbolatom 351 112 10 0 0 0 - - -; #X obj 159 201 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 127 127; #X obj 139 284 list split 1; #X obj 139 242 until; #X obj 139 263 list append; #X obj 139 219 t b l; #X obj 183 243 bang; #X obj 139 306 select 255; #X obj 139 328 i; #X obj 139 350 + 1; #X obj 139 372 t f f; #X obj 121 398 f; #X obj 114 108 metro 100; #X obj 114 85 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X msg 114 130 1; #X obj 79 323 t b b; #X msg 108 345 0; #X floatatom 121 555 5 0 0 3 dummyload - -; #X obj 253 378 -; #X obj 252 354 t f f; #X obj 253 400 select 1; #X obj 306 489 print error; #X obj 306 443 pack 0 0 0; #X obj 185 426 t f f; #X obj 373 416 + 1; #X obj 185 448 select 254; #X msg 185 470 -1; #X obj 206 328 t b f f f; #X msg 306 465 \$2 should be \$3; #X obj 306 421 t b b; #X obj 459 485 i; #X obj 459 507 + 1; #X obj 459 529 t f f; #X floatatom 459 551 5 0 0 3 errors - -; #X text 49 27 testing the server; #X floatatom 188 78 5 0 0 0 - - -; #X obj 55 394 i; #X obj 55 416 + 1; #X obj 55 438 t f f; #X floatatom 22 481 5 0 0 3 iterations - -; #X msg 56 372 0; #X obj 52 125 t b b; #X obj 52 147 timer; #X floatatom 52 169 5 0 0 0 - - -; #X obj 22 458 i; #X obj 14 344 metro 100; #X msg 14 366 bang; #X obj 16 325 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X connect 0 0 9 0; #X connect 0 1 5 0; #X connect 1 0 0 0; #X connect 2 0 3 0; #X connect 3 0 1 0; #X connect 4 0 3 0; #X connect 6 0 11 0; #X connect 6 1 8 1; #X connect 6 2 10 0; #X connect 7 0 8 0; #X connect 8 0 6 0; #X connect 9 0 7 0; #X connect 9 1 8 1; #X connect 10 0 7 1; #X connect 11 0 12 0; #X connect 11 1 31 0; #X connect 12 0 13 0; #X connect 13 0 14 0; #X connect 14 0 15 1; #X connect 14 1 12 1; #X connect 15 0 21 0; #X connect 16 0 18 0; #X connect 16 0 45 0; #X connect 17 0 16 0; #X connect 18 0 0 0; #X connect 19 0 15 0; #X connect 19 1 20 0; #X connect 19 1 40 0; #X connect 20 0 12 1; #X connect 22 0 24 0; #X connect 23 0 22 1; #X connect 23 1 22 0; #X connect 24 1 33 0; #X connect 26 0 32 0; #X connect 27 0 29 0; #X connect 27 1 28 0; #X connect 28 0 26 2; #X connect 29 0 30 0; #X connect 30 0 22 1; #X connect 31 0 19 0; #X connect 31 1 27 0; #X connect 31 2 23 0; #X connect 31 3 26 1; #X connect 32 0 25 0; #X connect 33 0 26 0; #X connect 33 1 34 0; #X connect 34 0 35 0; #X connect 35 0 36 0; #X connect 36 0 37 0; #X connect 36 1 34 1; #X connect 39 0 16 1; #X connect 40 0 41 0; #X connect 41 0 42 0; #X connect 42 0 48 1; #X connect 42 1 40 1; #X connect 44 0 40 0; #X connect 45 0 46 0; #X connect 45 1 46 1; #X connect 46 0 47 0; #X connect 48 0 43 0; #X connect 49 0 50 0; #X connect 50 0 48 0; #X connect 51 0 49 0; pd-iemnet-0.2.1/tests/sequence/01_tcpserver.pd000066400000000000000000000027601257237665700212410ustar00rootroot00000000000000#N canvas 219 165 438 532 10; #X obj 71 256 tcpserver 9999; #X obj 71 278 t b; #X obj 71 300 i; #X obj 115 326 + 1; #X obj 115 348 % 255; #X obj 250 252 loadbang; #X msg 71 388 broadcast \$1; #X obj 71 429 list append; #X obj 250 274 f 1024; #X obj 250 296 t b f b; #X obj 250 438 list prepend; #X obj 273 319 until; #X obj 273 341 f 255; #X obj 273 363 list prepend; #X obj 273 385 t l l; #X msg 106 276 bang; #X msg 321 250 bang; #X obj 71 451 list trim; #X obj 23 229 t a; #X text 27 43 responds to any data from the client by sending pack a stream consisting of a header and a dummy payload.; #X text 31 84 the dummy payload is a number of 0xFF bytes; #X obj 71 322 t f f; #X text 32 99 the header is a single byte counting up from 0..254 (and wrapping around); #X floatatom 166 305 5 0 0 0 - - -; #X obj 152 169 route sent; #X obj 152 191 unpack 0 0 0; #X floatatom 186 225 0 0 0 0 - - -; #X floatatom 221 211 5 0 0 0 - - -; #X connect 0 0 1 0; #X connect 0 4 24 0; #X connect 1 0 2 0; #X connect 2 0 21 0; #X connect 3 0 4 0; #X connect 4 0 2 1; #X connect 5 0 8 0; #X connect 6 0 7 0; #X connect 7 0 17 0; #X connect 8 0 9 0; #X connect 9 0 10 0; #X connect 9 1 11 0; #X connect 10 0 7 1; #X connect 11 0 12 0; #X connect 12 0 13 0; #X connect 13 0 14 0; #X connect 14 0 10 1; #X connect 14 1 13 1; #X connect 15 0 1 0; #X connect 16 0 8 0; #X connect 17 0 18 0; #X connect 18 0 0 0; #X connect 21 0 6 0; #X connect 21 1 3 0; #X connect 23 0 3 1; #X connect 24 0 25 0; #X connect 25 1 26 0; #X connect 25 2 27 0; pd-iemnet-0.2.1/tests/sequence/02_udpsendreceive.pd000066400000000000000000000041441257237665700222300ustar00rootroot00000000000000#N canvas 435 282 841 595 10; #X obj 106 234 udpsend; #X obj 106 24 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X obj 106 46 metro 100; #X floatatom 180 48 5 0 0 0 - - -; #X floatatom 206 151 5 1 65535 0 - - -; #X obj 151 336 t l l; #X obj 183 356 list length; #X obj 206 170 t f f; #X obj 151 400 t f f; #X obj 151 422 -; #X obj 151 514 +; #X obj 112 536 spigot; #X obj 112 558 print oops; #X obj 183 378 != 10; #X msg 151 493 1; #X msg 182 494 0; #X obj 151 447 select 1 -254; #X msg 394 144 2 \$1; #X obj 394 166 pow; #X floatatom 394 188 0 0 0 0 - - -; #X floatatom 386 55 5 0 0 0 - - -; #X obj 112 294 udpreceive 9999; #X msg 171 233 disconnect \, connect localhost 9999; #X obj 106 79 i 1; #X obj 106 101 until; #X floatatom 147 76 5 0 0 0 - - -; #X obj 316 336 t b b; #X obj 316 358 del 100; #X msg 316 380 0; #X obj 316 402 t f; #X msg 347 382 1; #X obj 316 424 change; #X floatatom 316 446 5 0 0 0 - - -; #X obj 106 127 ../packetgenerator; #X floatatom 275 301 5 0 0 0 - - -; #X obj 106 147 t l l; #X obj 133 184 ../bandwidth; #X symbolatom 133 206 10 0 0 0 - - -; #X obj 112 317 t l l b l; #X obj 391 319 ../bandwidth; #X symbolatom 391 341 10 0 0 0 - - -; #X connect 1 0 2 0; #X connect 2 0 23 0; #X connect 3 0 2 1; #X connect 4 0 7 0; #X connect 5 0 8 0; #X connect 5 1 6 0; #X connect 6 0 13 0; #X connect 7 0 33 1; #X connect 7 1 13 1; #X connect 8 0 9 1; #X connect 8 1 9 0; #X connect 9 0 16 0; #X connect 10 0 11 1; #X connect 11 0 12 0; #X connect 13 0 10 1; #X connect 14 0 10 0; #X connect 15 0 10 0; #X connect 16 0 15 0; #X connect 16 1 15 0; #X connect 16 2 14 0; #X connect 17 0 18 0; #X connect 18 0 19 0; #X connect 20 0 17 0; #X connect 21 0 34 0; #X connect 21 0 38 0; #X connect 22 0 0 0; #X connect 23 0 24 0; #X connect 24 0 33 0; #X connect 25 0 23 1; #X connect 26 0 27 0; #X connect 26 1 30 0; #X connect 27 0 28 0; #X connect 28 0 29 0; #X connect 29 0 31 0; #X connect 30 0 29 0; #X connect 31 0 32 0; #X connect 33 0 35 0; #X connect 35 0 0 0; #X connect 35 1 36 0; #X connect 36 0 37 0; #X connect 38 0 11 0; #X connect 38 1 5 0; #X connect 38 2 26 0; #X connect 38 3 39 0; #X connect 39 0 40 0; pd-iemnet-0.2.1/tests/tcpclient_reflect.sh000077500000000000000000000006571257237665700206220ustar00rootroot00000000000000#!/bin/sh PIPEFILE="pipe.$$" control_c() # run if user hits control-c { echo -en "\n*** Ouch! Exiting ***\n" rm -f ${PIPEFILE} exit $? } P=$1 PORT=$((P)) if [ ${PORT} -lt 1 ]; then echo "usage: $0 " 1>&2 exit 1 fi echo "register Ctrl-C" trap control_c SIGINT echo "make pipe" mknod ${PIPEFILE} p echo "start client" cat ${PIPEFILE} | nc -w 10 localhost ${PORT} > ${PIPEFILE} echo "client quit" rm ${PIPEFILE} pd-iemnet-0.2.1/tests/tcpclient_stress/000077500000000000000000000000001257237665700201525ustar00rootroot00000000000000pd-iemnet-0.2.1/tests/tcpclient_stress/01_crashertest.pd000066400000000000000000000031221257237665700233240ustar00rootroot00000000000000#N canvas 242 49 538 461 10; #X msg 433 315 disconnect; #X msg 204 173 connect localhost 44100; #X obj 335 71 list prepend broadcast; #X obj 335 93 list trim; #X obj 298 62 t a; #X obj 57 159 osc/packOSC; #X obj 57 299 osc/unpackOSC; #X obj 57 321 osc/routeOSC /metro; #X obj 57 345 osc/routeOSC /interval; #X obj 57 88 metro 10; #X obj 57 14 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X text 78 13 <- make pd crash; #X obj 204 146 loadbang; #X obj 57 397 b; #X obj 57 277 mrpeach/slipdec; #X obj 57 181 mrpeach/slipenc; #X obj 57 235 tcpclient; #X obj 335 44 tcpserver 44100; #X obj 57 111 random 100; #X msg 57 135 /metro/interval \$1; #X floatatom 57 370 5 0 0 0 - - -; #X obj 433 356 print -n; #X obj 57 418 del 1000; #X text 97 368 <- do we still receive something?; #X text 123 414 <- disconnect if not; #X obj 99 63 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1 ; #X msg 307 232 info; #X obj 433 278 spigot; #X obj 465 256 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X floatatom 134 68 5 0 0 0 - - -; #X connect 0 0 16 0; #X connect 0 0 21 0; #X connect 1 0 16 0; #X connect 2 0 3 0; #X connect 3 0 4 0; #X connect 4 0 17 0; #X connect 5 0 15 0; #X connect 6 0 7 0; #X connect 7 0 8 0; #X connect 8 0 20 0; #X connect 9 0 18 0; #X connect 10 0 9 0; #X connect 12 0 1 0; #X connect 13 0 22 0; #X connect 14 0 6 0; #X connect 15 0 16 0; #X connect 16 0 14 0; #X connect 17 0 2 0; #X connect 18 0 19 0; #X connect 19 0 5 0; #X connect 20 0 13 0; #X connect 22 0 27 0; #X connect 25 0 9 0; #X connect 26 0 16 0; #X connect 27 0 0 0; #X connect 28 0 27 1; #X connect 29 0 9 1; pd-iemnet-0.2.1/tests/tcpclient_stress/02_crasherclient.pd000066400000000000000000000070741257237665700236360ustar00rootroot00000000000000#N canvas 287 122 538 703 10; #X msg 433 315 disconnect; #X obj 57 179 osc/packOSC; #X obj 57 299 osc/unpackOSC; #X obj 57 321 osc/routeOSC /metro; #X obj 57 345 osc/routeOSC /interval; #X obj 57 88 metro 10; #X obj 57 14 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X text 78 13 <- make pd crash; #X obj 204 146 loadbang; #X obj 57 417 b; #X obj 57 277 mrpeach/slipdec; #X obj 57 201 mrpeach/slipenc; #X obj 57 235 tcpclient; #X obj 57 111 random 100; #X msg 57 155 /metro/interval \$1; #X floatatom 31 485 5 0 0 0 - - -; #X obj 433 356 print -n; #X obj 57 438 del 1000; #X text 101 401 <- do we still receive something?; #X text 123 434 <- disconnect if not; #X obj 99 63 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1 ; #X msg 307 232 info; #X obj 433 278 spigot; #X obj 465 256 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X msg 291 260 debug \$1; #X floatatom 363 230 5 0 0 0 - - -; #X msg 360 202 6; #X msg 136 89 bang; #X msg 408 205 2; #X msg 404 125 15; #X msg 419 173 31; #X obj 433 337 t a a; #X msg 18 203 bang; #X msg 468 220 14; #X msg 376 247 0; #X obj -17 276 loadbang; #X msg -17 343 set -1; #X obj -17 301 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 1; #X msg 204 173 connect localhost 44101; #X obj -17 321 metro 1000; #X obj 62 258 t a a; #X obj 317 427 spigot; #X obj 317 449 print data; #X obj 373 428 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X obj 278 17 tgl 100 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 1; #X obj 278 122 select 1 0; #X floatatom 141 59 5 0 0 0 - - -; #X obj 280 552 i; #X obj 280 574 + 1; #X obj 280 596 t f f; #X obj 70 369 t a b; #X obj 200 552 i; #X obj 200 574 + 1; #X obj 200 596 t f f; #X msg 371 581 0; #X floatatom 200 649 5 0 0 0 - - -; #X obj 218 617 r gui; #X obj 200 632 spigot 1; #X floatatom 280 649 5 0 0 0 - - -; #X obj 298 617 r gui; #X obj 280 632 spigot 1; #X obj 31 395 t f b; #X obj 49 453 r gui; #X obj 31 468 spigot 1; #X obj 81 591 s gui; #X obj 81 571 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 1; #X floatatom 166 130 5 0 0 0 - - -; #X obj 184 98 r gui; #X obj 166 113 spigot 1; #X obj 57 132 t a b f; #X connect 0 0 31 0; #X connect 1 0 11 0; #X connect 2 0 3 0; #X connect 3 0 4 0; #X connect 4 0 50 0; #X connect 5 0 13 0; #X connect 6 0 5 0; #X connect 9 0 17 0; #X connect 10 0 2 0; #X connect 11 0 12 0; #X connect 12 0 40 0; #X connect 13 0 69 0; #X connect 14 0 1 0; #X connect 17 0 22 0; #X connect 20 0 5 0; #X connect 21 0 12 0; #X connect 22 0 0 0; #X connect 23 0 22 1; #X connect 24 0 12 0; #X connect 25 0 24 0; #X connect 26 0 25 0; #X connect 27 0 13 0; #X connect 28 0 25 0; #X connect 29 0 25 0; #X connect 30 0 25 0; #X connect 31 0 12 0; #X connect 31 1 16 0; #X connect 32 0 12 0; #X connect 33 0 25 0; #X connect 34 0 25 0; #X connect 35 0 37 0; #X connect 36 0 15 0; #X connect 37 0 39 0; #X connect 38 0 12 0; #X connect 39 0 36 0; #X connect 40 0 10 0; #X connect 40 1 41 0; #X connect 41 0 42 0; #X connect 43 0 41 1; #X connect 44 0 45 0; #X connect 45 0 38 0; #X connect 45 1 0 0; #X connect 46 0 5 1; #X connect 47 0 48 0; #X connect 48 0 49 0; #X connect 49 0 60 0; #X connect 49 1 47 1; #X connect 50 0 61 0; #X connect 50 1 51 0; #X connect 51 0 52 0; #X connect 52 0 53 0; #X connect 53 0 57 0; #X connect 53 1 51 1; #X connect 54 0 53 0; #X connect 54 0 49 0; #X connect 56 0 57 1; #X connect 57 0 55 0; #X connect 59 0 60 1; #X connect 60 0 58 0; #X connect 61 0 63 0; #X connect 61 1 9 0; #X connect 62 0 63 1; #X connect 63 0 15 0; #X connect 65 0 64 0; #X connect 67 0 68 1; #X connect 68 0 66 0; #X connect 69 0 14 0; #X connect 69 1 47 0; #X connect 69 2 68 0; pd-iemnet-0.2.1/tests/tcpclient_stress/02_crasherserver.pd000066400000000000000000000007701257237665700236620ustar00rootroot00000000000000#N canvas 642 62 538 461 10; #X obj 335 71 list prepend broadcast; #X obj 335 93 list trim; #X obj 335 44 tcpserver 44101; #X msg 175 45 debug \$1; #X floatatom 164 20 5 0 0 0 - - -; #X obj 286 91 t a a; #X obj 320 248 print aaa; #X obj 321 226 spigot; #X obj 377 227 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X connect 0 0 1 0; #X connect 1 0 5 0; #X connect 2 0 0 0; #X connect 3 0 2 0; #X connect 4 0 3 0; #X connect 5 0 2 0; #X connect 5 1 7 0; #X connect 7 0 6 0; #X connect 8 0 7 1; pd-iemnet-0.2.1/tests/tcpserver.py000077500000000000000000000020431257237665700171530ustar00rootroot00000000000000#!/usr/bin/env python import SocketServer class MyTCPHandler(SocketServer.BaseRequestHandler): """ The RequestHandler class for our server. It is instantiated once per connection to the server, and must override the handle() method to implement communication to the client. """ def handle(self): # self.request is the TCP socket connected to the client self.data = self.request.recv(1024).strip() print "{} wrote:".format(self.client_address[0]) print self.data # just send back the same data, but upper-cased self.request.sendall(self.data.upper()) if __name__ == "__main__": import sys HOST, PORT = "localhost", 9999 if len(sys.argv)>1: PORT=int(sys.argv[1]) print("binding to %s:%s" % (HOST, PORT)) # Create the server, binding to localhost on port 9999 server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler) # Activate the server; this will keep running until you # interrupt the program with Ctrl-C server.serve_forever() pd-iemnet-0.2.1/tests/tcpserver_reflect.sh000077500000000000000000000006451257237665700206470ustar00rootroot00000000000000#!/bin/sh PIPEFILE="pipe.$$" control_c() # run if user hits control-c { echo -en "\n*** Ouch! Exiting ***\n" rm -f ${PIPEFILE} exit $? } P=$1 PORT=$((P)) if [ ${PORT} -lt 1 ]; then echo "usage: $0 " 1>&2 exit 1 fi echo "register Ctrl-C" trap control_c SIGINT echo "make pipe" mknod ${PIPEFILE} p echo "start server" cat ${PIPEFILE} | nc -l -p ${PORT} > ${PIPEFILE} echo "server quit" rm ${PIPEFILE} pd-iemnet-0.2.1/tests/tcpsink.sh000077500000000000000000000002001257237665700165640ustar00rootroot00000000000000#!/bin/sh P=$1 PORT=$((P)) if [ ${PORT} -lt 1 ]; then echo "usage: $0 " 1>&2 exit 1 fi nc -l -p ${PORT} > /dev/null pd-iemnet-0.2.1/tests/tcpsource.sh000077500000000000000000000002451257237665700171310ustar00rootroot00000000000000#!/bin/sh P=$1 PORT=$((P)) if [ ${PORT} -lt 1 ]; then echo "usage: $0 " 1>&2 exit 1 fi yes abcdefghijklmnopqrstuvwxyz | nc localhost ${PORT} > /dev/null pd-iemnet-0.2.1/tests/udpclient_reflect.sh000077500000000000000000000007151257237665700206170ustar00rootroot00000000000000#!/bin/sh PIPEFILE="pipe.$$" control_c() # run if user hits control-c { echo -en "\n*** Ouch! Exiting ***\n" rm -f ${PIPEFILE} exit $? } P=$1 PORT=$((P)) if [ ${PORT} -lt 1 ]; then echo "usage: $0 " 1>&2 exit 1 fi echo "register Ctrl-C" trap control_c SIGINT echo "make pipe" mknod ${PIPEFILE} p echo "UDP" > ${PIPEFILE} & echo "start client" cat ${PIPEFILE} | nc -w 10 -u localhost ${PORT} > ${PIPEFILE} echo "client quit" rm ${PIPEFILE} pd-iemnet-0.2.1/tests/udpserver_reflect.sh000077500000000000000000000006561257237665700206530ustar00rootroot00000000000000#!/bin/sh PIPEFILE="pipe.$$" control_c() # run if user hits control-c { echo -en "\n*** Ouch! Exiting ***\n" rm -f ${PIPEFILE} exit $? } P=$1 PORT=$((P)) if [ ${PORT} -lt 1 ]; then echo "usage: $0 " 1>&2 exit 1 fi echo "register Ctrl-C" trap control_c SIGINT echo "make pipe" mknod ${PIPEFILE} p echo "start server" cat ${PIPEFILE} | nc -w 10 -u -l -p ${PORT} > ${PIPEFILE} echo "server quit" rm ${PIPEFILE} pd-iemnet-0.2.1/tests/udpsink.sh000077500000000000000000000002031257237665700165710ustar00rootroot00000000000000#!/bin/sh P=$1 PORT=$((P)) if [ ${PORT} -lt 1 ]; then echo "usage: $0 " 1>&2 exit 1 fi nc -u -l -p ${PORT} > /dev/null pd-iemnet-0.2.1/tests/udpsource.sh000077500000000000000000000002501257237665700171270ustar00rootroot00000000000000#!/bin/sh P=$1 PORT=$((P)) if [ ${PORT} -lt 1 ]; then echo "usage: $0 " 1>&2 exit 1 fi yes abcdefghijklmnopqrstuvwxyz | nc -u localhost ${PORT} > /dev/null pd-iemnet-0.2.1/udpclient-help.pd000066400000000000000000000062101257237665700166610ustar00rootroot00000000000000#N canvas 4 49 1100 592 12; #X msg 116 117 disconnect; #X floatatom 255 351 3 0 0 0 - - -, f 3; #X floatatom 284 351 3 0 0 0 - - -, f 3; #X floatatom 311 351 3 0 0 0 - - -, f 3; #X floatatom 336 351 3 0 0 0 - - -, f 3; #X text 219 351 from; #X obj 275 307 tgl 15 0 empty empty connected 18 7 0 8 -24198 -241291 -1 0 1; #X text 197 21 connect with an IP address and port number; #X text 44 257 See also:; #X msg 21 22 connect 127.0.0.1 9997; #X text 414 176 semicolon-terminated string for netserver or netreceive ; #X text 322 202 'send' prefix is optional; #X obj 235 412 spigot; #X obj 274 389 tgl 15 0 empty empty enable_print 18 7 0 8 -24198 -241291 -1 0 1; #X floatatom 872 280 9 0 0 0 - - -, f 9; #X text 40 399 2010/03/01 Martin Peach; #X text 438 440 Attempting to print long messages can hang Pd!; #X obj 872 256 route sent; #X text 944 280 sent bytes; #X floatatom 872 437 3 0 0 0 - - -, f 3; #X floatatom 926 437 3 0 0 0 - - -, f 3; #X floatatom 899 437 3 0 0 0 - - -, f 3; #X obj 872 358 route address; #X obj 872 386 unpack f f f f f; #X floatatom 953 437 3 0 0 0 - - -, f 3; #X floatatom 981 411 6 0 0 0 - - -, f 6; #X text 979 437 ip; #X text 1027 430 port; #X obj 520 344 spigot; #X obj 559 321 tgl 15 0 empty empty enable_print 18 7 0 8 -24198 -241291 -1 0 1; #X text 286 411 Received messages are output as a stream of bytes; #X text 45 477 NOTE: outlet's #2 & #3 are for compatibility with mrpeach's net objects. all information is available via outlet#4 as well!; #X obj 45 279 udpreceive; #X obj 45 302 udpserver; #X text 40 414 2010/10/08 Roman Haefeli; #X obj 235 256 udpclient; #X obj 235 441 print udpclient:received; #X obj 520 373 print udpclient:status; #X obj 255 328 unpack f f f f f; #X floatatom 364 351 6 0 0 0 - - -, f 6; #X msg 148 149 send 47 116 101 115 116 32 104 101 108 108 111 10; #X msg 176 177 send 51 49 32 97 98 99 59 10; #X text 552 148 /test hello (OSC message); #X text 312 255 udpclient can be used for a bi-directional connection ; #X msg 203 204 97 98 99 100 10; #X msg 47 48 connect swisstime.ethz.ch 13; #X text 547 14 udpclient can connect to a server and send and receive messages as lists of bytes. Any integer value between 0 and 255 can be transmitted or received.; #X obj 295 281 s \$0.udpclient.o4; #X obj 520 298 r \$0.udpclient.o4; #X obj 872 232 r \$0.udpclient.o4; #X obj 872 332 r \$0.udpclient.o4; #X msg 74 75 connect 127.0.0.1 7999 7999; #X text 303 67 optional second argument to set the local port (where we receive the returning messages) \; default is to choose any available port.; #X connect 0 0 35 0; #X connect 9 0 35 0; #X connect 12 0 36 0; #X connect 13 0 12 1; #X connect 17 0 14 0; #X connect 22 0 23 0; #X connect 23 0 19 0; #X connect 23 1 21 0; #X connect 23 2 20 0; #X connect 23 3 24 0; #X connect 23 4 25 0; #X connect 28 0 37 0; #X connect 29 0 28 1; #X connect 35 0 12 0; #X connect 35 1 38 0; #X connect 35 2 6 0; #X connect 35 3 47 0; #X connect 38 0 1 0; #X connect 38 1 2 0; #X connect 38 2 3 0; #X connect 38 3 4 0; #X connect 38 4 39 0; #X connect 40 0 35 0; #X connect 41 0 35 0; #X connect 44 0 35 0; #X connect 45 0 35 0; #X connect 48 0 28 0; #X connect 49 0 17 0; #X connect 50 0 22 0; #X connect 51 0 35 0; pd-iemnet-0.2.1/udpclient.c000066400000000000000000000206731257237665700155630ustar00rootroot00000000000000/* udpclient.c * copyright © 2010-2015 IOhannes m zmölnig, IEM */ /* */ /* A client for bidirectional communication from within Pd. */ /* */ /* This program is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation; either version 2 */ /* of the License, or (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, see */ /* http://www.gnu.org/licenses/ */ /* */ /* ---------------------------------------------------------------------------- */ #define DEBUGLEVEL 1 #include "iemnet.h" #include #include static t_class *udpclient_class; static const char objName[] = "udpclient"; typedef struct _udpclient { t_object x_obj; t_outlet *x_msgout; t_outlet *x_addrout; t_outlet *x_connectout; t_outlet *x_statusout; t_iemnet_sender*x_sender; t_iemnet_receiver*x_receiver; int x_fd; // the socket char *x_hostname; // address we want to connect to as text int x_connectstate; // 0 = not connected, 1 = connected u_short x_port; // port we're sending to u_short x_sendport; // port we're sending from long x_addr; // address we're connected to as 32bit int t_iemnet_floatlist *x_floatlist; } t_udpclient; /* forward declarations */ static void udpclient_receive_callback(void *x, t_iemnet_chunk*); /* connection handling */ static void *udpclient_doconnect(t_udpclient*x, int subthread) { struct sockaddr_in server; struct hostent *hp; int sockfd; int broadcast = 1;/* nonzero is true */ memset(&server, 0, sizeof(server)); if (x->x_sender) { iemnet_log(x, IEMNET_ERROR, "already connected"); return (x); } /* connect socket using hostname provided in command line */ hp = gethostbyname(x->x_hostname); if (hp == 0) { iemnet_log(x, IEMNET_ERROR, "bad host '%s'?", x->x_hostname); return (x); } server.sin_family = AF_INET; /* create a socket */ sockfd = socket(AF_INET, SOCK_DGRAM, 0); DEBUG("send socket %d\n", sockfd); if (sockfd < 0) { iemnet_log(x, IEMNET_ERROR, "unable to create socket"); sys_sockerror("socket"); return (x); } /* Enable sending of broadcast messages (if hostname is a broadcast address) */ #ifdef SO_BROADCAST if( 0 != setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (const void *)&broadcast, sizeof(broadcast))) { iemnet_log(x, IEMNET_ERROR, "unable to switch to broadcast mode"); sys_sockerror("setsockopt"); } #endif /* SO_BROADCAST */ if(x->x_sendport>0) { server.sin_family = AF_INET; server.sin_port = htons(x->x_sendport); server.sin_addr.s_addr = INADDR_ANY; if (bind(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) { iemnet_log(x, IEMNET_ERROR, "unable to bind with sending port %d (continuing with random port)", x->x_sendport); sys_sockerror("bind"); } } /* try to connect. */ /* assign client port number */ memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); server.sin_port = htons(x->x_port); DEBUG("connecting to %s:%d", x->x_hostname, x->x_port); if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) { iemnet_log(x, IEMNET_ERROR, "unable to connect to stream socket"); sys_sockerror("connect"); iemnet__closesocket(sockfd, 1); return (x); } x->x_fd = sockfd; x->x_addr = ntohl(*(long *)hp->h_addr); x->x_sender=iemnet__sender_create(sockfd, NULL, NULL, subthread); x->x_receiver=iemnet__receiver_create(sockfd, x, udpclient_receive_callback, subthread); x->x_connectstate = 1; outlet_float(x->x_connectout, 1); return (x); } static int udpclient_do_disconnect(t_udpclient *x) { DEBUG("disconnect %x %x", x->x_sender, x->x_receiver); if(x->x_receiver) { iemnet__receiver_destroy(x->x_receiver, 0); } x->x_receiver=NULL; if(x->x_sender) { iemnet__sender_destroy(x->x_sender, 0); } x->x_sender=NULL; x->x_connectstate = 0; if (x->x_fd < 0) { return 0; } iemnet__closesocket(x->x_fd, 1); x->x_fd = -1; return 1; } static void udpclient_disconnect(t_udpclient *x) { if(!udpclient_do_disconnect(x)) { iemnet_log(x, IEMNET_ERROR, "not connected"); } else { outlet_float(x->x_connectout, 0); } } static void udpclient_connect(t_udpclient *x, t_symbol *hostname, t_floatarg fportno, t_floatarg fsndportno) { if(x->x_fd>=0) { udpclient_disconnect(x); } /* we get hostname and port and pass them on to the child thread that establishes the connection */ x->x_hostname = hostname->s_name; x->x_port = fportno; x->x_sendport = (fsndportno>0)?fsndportno:0; x->x_connectstate = 0; udpclient_doconnect(x, 0); } /* sending/receiving */ static void udpclient_send(t_udpclient *x, t_symbol *s, int argc, t_atom *argv) { int size=0; t_atom output_atom; t_iemnet_sender*sender=x->x_sender; t_iemnet_chunk*chunk=iemnet__chunk_create_list(argc, argv); if(sender && chunk) { size=iemnet__sender_send(sender, chunk); } iemnet__chunk_destroy(chunk); SETFLOAT(&output_atom, size); outlet_anything( x->x_statusout, gensym("sendbuffersize"), 1, &output_atom); } static void udpclient_receive_callback(void*y, t_iemnet_chunk*c) { t_udpclient *x=(t_udpclient*)y; if(c) { iemnet__addrout(x->x_statusout, x->x_addrout, x->x_addr, x->x_port); x->x_floatlist=iemnet__chunk2list(c, x->x_floatlist); /* gets destroyed in the dtor */ outlet_list(x->x_msgout, gensym("list"),x->x_floatlist->argc, x->x_floatlist->argv); } else { // disconnected DEBUG("disconnected"); if(x->x_fd >= 0) { udpclient_disconnect(x); } } } /* constructor/destructor */ static void *udpclient_new(void) { t_udpclient *x = (t_udpclient *)pd_new(udpclient_class); x->x_msgout = outlet_new(&x->x_obj, 0); /* received data */ x->x_addrout = outlet_new(&x->x_obj, gensym("list")); x->x_connectout = outlet_new(&x->x_obj, gensym("float")); /* connection state */ x->x_statusout = outlet_new(&x->x_obj, 0); /* last outlet for everything else */ x->x_fd = -1; x->x_addr = 0L; x->x_port = 0; x->x_sender=NULL; x->x_receiver=NULL; x->x_floatlist=iemnet__floatlist_create(1024); return (x); } static void udpclient_free(t_udpclient *x) { udpclient_do_disconnect(x); if(x->x_floatlist) { iemnet__floatlist_destroy(x->x_floatlist); } x->x_floatlist=NULL; } IEMNET_EXTERN void udpclient_setup(void) { if(!iemnet__register(objName)) { return; } udpclient_class = class_new(gensym(objName), (t_newmethod)udpclient_new, (t_method)udpclient_free, sizeof(t_udpclient), 0, A_DEFFLOAT, 0); class_addmethod(udpclient_class, (t_method)udpclient_connect, gensym("connect") , A_SYMBOL, A_FLOAT, A_DEFFLOAT, 0); class_addmethod(udpclient_class, (t_method)udpclient_disconnect, gensym("disconnect"), 0); class_addmethod(udpclient_class, (t_method)udpclient_send, gensym("send"), A_GIMME, 0); class_addlist(udpclient_class, (t_method)udpclient_send); DEBUGMETHOD(udpclient_class); } IEMNET_INITIALIZER(udpclient_setup); /* end of udpclient.c */ pd-iemnet-0.2.1/udpreceive-help.pd000066400000000000000000000030731257237665700170310ustar00rootroot00000000000000#N canvas 60 148 478 280 12; #X floatatom 158 142 3 0 0 0 - - -; #X floatatom 185 142 3 0 0 0 - - -; #X floatatom 212 142 3 0 0 0 - - -; #X floatatom 239 142 3 0 0 0 - - -; #X text 115 141 from; #X obj 107 186 print message; #X obj 107 91 udpreceive 9997; #X text 32 16 udpreceive receives bytes over a udp connection.; #X floatatom 267 142 5 0 0 0 - - -; #X obj 158 116 unpack 0 0 0 0 0; #X msg 107 50 port 8888; #X text 182 48 change the port; #X text 34 229 copyright (c) 2008 Martin Peach; #X text 34 249 copyright (c) 2010 IOhannes m zmoelnig (for iemnet) ; #N canvas 3 45 450 300 get.info 0; #X text 29 31 NOTE outlet #2 is for compatibility with mrpeach's net objects. you can get all info (and more) via outlet #3 as well.; #X obj 40 95 inlet outlet#3; #X obj 40 119 route address; #X floatatom 190 177 3 0 0 0 - - -; #X floatatom 217 177 3 0 0 0 - - -; #X floatatom 244 177 3 0 0 0 - - -; #X floatatom 271 177 3 0 0 0 - - -; #X text 147 176 from; #X floatatom 299 177 5 0 0 0 - - -; #X obj 190 151 unpack 0 0 0 0 0; #X obj 35 213 route port; #X floatatom 197 245 5 0 0 0 - - -; #X text 236 244 listening port; #X connect 1 0 2 0; #X connect 2 0 9 0; #X connect 2 1 10 0; #X connect 9 0 3 0; #X connect 9 1 4 0; #X connect 9 2 5 0; #X connect 9 3 6 0; #X connect 9 4 8 0; #X connect 10 0 11 0; #X restore 317 111 pd get.info; #X text 373 159 check also:; #X obj 375 182 udpsend; #X obj 375 208 udpserver; #X connect 6 0 5 0; #X connect 6 1 9 0; #X connect 6 2 14 0; #X connect 9 0 0 0; #X connect 9 1 1 0; #X connect 9 2 2 0; #X connect 9 3 3 0; #X connect 9 4 8 0; #X connect 10 0 6 0; pd-iemnet-0.2.1/udpreceive.c000066400000000000000000000166161257237665700157310ustar00rootroot00000000000000/* udpreceive.c * copyright © 2010-2015 IOhannes m zmölnig, IEM * copyright (c) 2006-2010 Martin Peach * copyright (c) Miller Puckette */ /* */ /* A server for unidirectional communication from within Pd. */ /* */ /* This program is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation; either version 2 */ /* of the License, or (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, see */ /* http://www.gnu.org/licenses/ */ #define DEBUGLEVEL 1 static const char objName[] = "udpreceive"; #include "iemnet.h" #include /* ----------------------------- udpreceive ------------------------- */ static t_class *udpreceive_class; typedef struct _udpreceive { t_object x_obj; t_outlet *x_msgout; t_outlet *x_addrout; t_outlet *x_statout; int x_fd; int x_port; t_iemnet_receiver *x_receiver; t_iemnet_floatlist*x_floatlist; int x_reuseport, x_reuseaddr; } t_udpreceive; static void udpreceive_read_callback(void*y, t_iemnet_chunk*c) { t_udpreceive*x=(t_udpreceive*)y; if(c) { iemnet__addrout(x->x_statout, x->x_addrout, c->addr, c->port); x->x_floatlist=iemnet__chunk2list(c, x->x_floatlist); // gets destroyed in the dtor outlet_list(x->x_msgout, gensym("list"), x->x_floatlist->argc, x->x_floatlist->argv); } else { iemnet_log(x, IEMNET_VERBOSE, "nothing received"); } } static int udpreceive_setport(t_udpreceive*x, unsigned short portno) { struct sockaddr_in server; socklen_t serversize=sizeof(server); int sockfd = x->x_fd; int intarg; memset(&server, 0, sizeof(server)); if(x->x_port == portno) { iemnet_log(x, IEMNET_VERBOSE, "skipping re-binding to port:%d", portno); return 1; } /* cleanup any open ports */ if(x->x_receiver) { iemnet__receiver_destroy(x->x_receiver, 0); x->x_receiver=NULL; } if(sockfd>=0) { iemnet__closesocket(sockfd, 1); x->x_fd=-1; x->x_port=-1; } sockfd = socket(AF_INET, SOCK_DGRAM, 0); if(sockfd<0) { iemnet_log(x, IEMNET_ERROR, "unable to create socket"); sys_sockerror("socket"); return 0; } /* ask OS to allow another Pd to reopen this port after we close it. */ #ifdef SO_REUSEADDR if(x->x_reuseaddr) { intarg = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&intarg, sizeof(intarg)) < 0) { iemnet_log(x, IEMNET_ERROR, "unable to enable address re-using"); sys_sockerror("setsockopt:SO_REUSEADDR"); } } #endif /* SO_REUSEADDR */ #ifdef SO_REUSEPORT if(x->x_reuseport) { intarg = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (void *)&intarg, sizeof(intarg)) < 0) { iemnet_log(x, IEMNET_ERROR, "unable to enable port re-using"); sys_sockerror("setsockopt:SO_REUSEPORT"); } } #endif /* SO_REUSEPORT */ server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons((u_short)portno); /* name the socket */ if (bind(sockfd, (struct sockaddr *)&server, serversize) < 0) { iemnet_log(x, IEMNET_ERROR, "unable to bind to socket"); sys_sockerror("bind"); iemnet__closesocket(sockfd, 1); sockfd = -1; return 0; } x->x_fd = sockfd; x->x_port = portno; // find out which port is actually used (useful when assigning "0") if(!getsockname(sockfd, (struct sockaddr *)&server, &serversize)) { x->x_port=ntohs(server.sin_port); } x->x_receiver=iemnet__receiver_create(sockfd, x, udpreceive_read_callback, 0); return 1; } static void udpreceive_port(t_udpreceive*x, t_symbol*s, int argc, t_atom*argv) { t_atom ap[1]; if(argc) { if(argc>1 || A_FLOAT != argv->a_type) { iemnet_log(x, IEMNET_ERROR, "usage: %s []", s->s_name); return; } SETFLOAT(ap, -1); if(!udpreceive_setport(x, atom_getint(argv))) { outlet_anything(x->x_statout, gensym("port"), 1, ap); } } SETFLOAT(ap, x->x_port); outlet_anything(x->x_statout, gensym("port"), 1, ap); } static void udpreceive_optionI(t_udpreceive*x, t_symbol*s, int argc, t_atom*argv) { int*reuse=NULL; if(gensym("reuseport")==s) { reuse=&x->x_reuseport; } if(gensym("reuseaddr")==s) { reuse=&x->x_reuseaddr; } if(!reuse) { iemnet_log(x, IEMNET_ERROR, "unknown option '%s'", s->s_name); return; } if(argc) { if(1==argc && A_FLOAT == argv->a_type) { *reuse=atom_getint(argv); return; } else { iemnet_log(x, IEMNET_ERROR, "usage: %s []", s->s_name); return; } } else { t_atom ap[1]; SETFLOAT(ap, *reuse); outlet_anything(x->x_statout, s, 1, ap); } } static void *udpreceive_new(t_floatarg fportno) { t_udpreceive*x = (t_udpreceive *)pd_new(udpreceive_class); x->x_msgout = outlet_new(&x->x_obj, 0); x->x_addrout = outlet_new(&x->x_obj, gensym("list")); x->x_statout = outlet_new(&x->x_obj, 0); x->x_fd = -1; x->x_port = -1; x->x_receiver = NULL; x->x_floatlist=iemnet__floatlist_create(1024); x->x_reuseaddr = 1; x->x_reuseport = 0; udpreceive_setport(x, fportno); return (x); } static void udpreceive_free(t_udpreceive *x) { if(x->x_receiver) { iemnet__receiver_destroy(x->x_receiver, 0); } x->x_receiver=NULL; if(x->x_fd >= 0) { iemnet__closesocket(x->x_fd, 0); } x->x_fd=-1; outlet_free(x->x_msgout); outlet_free(x->x_addrout); outlet_free(x->x_statout); if(x->x_floatlist) { iemnet__floatlist_destroy(x->x_floatlist); } x->x_floatlist=NULL; } IEMNET_EXTERN void udpreceive_setup(void) { if(!iemnet__register(objName)) { return; } udpreceive_class = class_new(gensym(objName), (t_newmethod)udpreceive_new, (t_method)udpreceive_free, sizeof(t_udpreceive), 0, A_DEFFLOAT, 0); class_addmethod(udpreceive_class, (t_method)udpreceive_port, gensym("port"), A_GIMME, 0); /* options for opening new sockets */ class_addmethod(udpreceive_class, (t_method)udpreceive_optionI, gensym("reuseaddr"), A_GIMME, 0); class_addmethod(udpreceive_class, (t_method)udpreceive_optionI, gensym("reuseport"), A_GIMME, 0); DEBUGMETHOD(udpreceive_class); } IEMNET_INITIALIZER(udpreceive_setup); /* end udpreceive.c */ pd-iemnet-0.2.1/udpsend-help.pd000066400000000000000000000015711257237665700163410ustar00rootroot00000000000000#N canvas 76 70 590 348 12; #X msg 72 182 disconnect; #X msg 16 59 connect 127.0.0.1 9997; #X obj 16 306 tgl 15 0 empty empty connected 20 7 0 8 -24198 -241291 -1 0 1; #X text 220 60 <--first; #X msg 25 101 send 0 1 2 3; #X text 8 5 udpsend sends bytes over a udp connection.; #X text 8 28 Used in conjunction with packOSC will send OSC over udp ; #X obj 16 283 udpsend; #X text 141 101 send raw data; #X msg 40 126 99 98 97; #X text 106 128 'send' prefix is optional; #X text 202 293 (c) copyright 2007 Martin Peach; #X text 201 311 (c) copyright 2010 IOhannes m zmoelnig; #X text 171 208 NOTE: with the iemnet version of [udpsend] you CANNOT send files directly! use mrpeach's [binfile] to read the file.; #X text 406 85 check also:; #X obj 409 110 udpclient; #X obj 409 137 udpreceive; #X connect 0 0 7 0; #X connect 1 0 7 0; #X connect 4 0 7 0; #X connect 7 0 2 0; #X connect 9 0 7 0; pd-iemnet-0.2.1/udpsend.c000066400000000000000000000121271257237665700152310ustar00rootroot00000000000000/* udpsend.c * copyright © 2010-2015 IOhannes m zmölnig, IEM * copyright (c) 2006-2010 Martin Peach * copyright (c) Miller Puckette */ /* */ /* A client for unidirectional communication from within Pd. */ /* */ /* This program is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation; either version 2 */ /* of the License, or (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, see */ /* http://www.gnu.org/licenses/ */ /* */ #define DEBUGLEVEL 1 static const char objName[] = "udpsend"; #include "iemnet.h" #include static t_class *udpsend_class; typedef struct _udpsend { t_object x_obj; t_iemnet_sender*x_sender; int x_fd; } t_udpsend; static void udpsend_connect(t_udpsend *x, t_symbol *hostname, t_floatarg fportno) { struct sockaddr_in server; struct hostent *hp = NULL; int sockfd; int portno = fportno; int broadcast = 1;/* nonzero is true */ memset(&server, 0, sizeof(server)); if (x->x_sender) { iemnet_log(x, IEMNET_ERROR, "already connected"); return; } /* connect socket using hostname provided in command line */ server.sin_family = AF_INET; hp = gethostbyname(hostname->s_name); if (hp == 0) { iemnet_log(x, IEMNET_ERROR, "bad host '%s'?", hostname->s_name); return; } memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); /* assign client port number */ server.sin_port = htons((u_short)portno); DEBUG("connecting to port %d", portno); /* create a socket */ sockfd = socket(AF_INET, SOCK_DGRAM, 0); DEBUG("send socket %d\n", sockfd); if (sockfd < 0) { iemnet_log(x, IEMNET_ERROR, "unable to create datagram socket"); sys_sockerror("socket"); return; } /* Enable sending of broadcast messages (if hostname is a broadcast address)*/ #ifdef SO_BROADCAST if( 0 != setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (const void *)&broadcast, sizeof(broadcast))) { iemnet_log(x, IEMNET_ERROR, "unable to switch to broadcast mode"); sys_sockerror("setsockopt:SO_BROADCAST"); } #endif /* SO_BROADCAST */ /* try to connect. */ if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) { iemnet_log(x, IEMNET_ERROR, "unable to connect to socket:%d", sockfd); sys_sockerror("connect"); iemnet__closesocket(sockfd, 1); return; } x->x_sender=iemnet__sender_create(sockfd, NULL, NULL, 0); x->x_fd = sockfd; outlet_float(x->x_obj.ob_outlet, 1); } static void udpsend_disconnect(t_udpsend *x) { if(x->x_sender) { iemnet__sender_destroy(x->x_sender, 0); } x->x_sender=NULL; if(x->x_fd >= 0) { iemnet__closesocket(x->x_fd, 1); x->x_fd=-1; outlet_float(x->x_obj.ob_outlet, 0); } } static void udpsend_send(t_udpsend *x, t_symbol *s, int argc, t_atom *argv) { if(x->x_sender) { t_iemnet_chunk*chunk=iemnet__chunk_create_list(argc, argv); iemnet__sender_send(x->x_sender, chunk); iemnet__chunk_destroy(chunk); } else { iemnet_log(x, IEMNET_ERROR, "not connected"); } } static void udpsend_free(t_udpsend *x) { udpsend_disconnect(x); } static void *udpsend_new(void) { t_udpsend *x = (t_udpsend *)pd_new(udpsend_class); outlet_new(&x->x_obj, gensym("float")); x->x_sender=NULL; x->x_fd=-1; return (x); } IEMNET_EXTERN void udpsend_setup(void) { if(!iemnet__register(objName)) { return; } udpsend_class = class_new(gensym(objName), (t_newmethod)udpsend_new, (t_method)udpsend_free, sizeof(t_udpsend), 0, 0); class_addmethod(udpsend_class, (t_method)udpsend_connect, gensym("connect"), A_SYMBOL, A_FLOAT, 0); class_addmethod(udpsend_class, (t_method)udpsend_disconnect, gensym("disconnect"), 0); class_addmethod(udpsend_class, (t_method)udpsend_send, gensym("send"), A_GIMME, 0); class_addlist(udpsend_class, (t_method)udpsend_send); DEBUGMETHOD(udpsend_class); } IEMNET_INITIALIZER(udpsend_setup); /* end udpsend.c*/ pd-iemnet-0.2.1/udpserver-help.pd000066400000000000000000000072361257237665700167220ustar00rootroot00000000000000#N canvas 3 45 858 382 12; #X floatatom 78 159 5 0 0 0 - - -; #X floatatom 102 189 5 0 0 0 - - -; #X floatatom 126 239 3 0 0 0 - - -; #X floatatom 153 239 3 0 0 0 - - -; #X floatatom 180 239 3 0 0 0 - - -; #X floatatom 207 239 3 0 0 0 - - -; #X text 89 238 from; #X text -6 159 connections; #X msg 55 61 broadcast 1 2 3; #X text 173 62 send to all clients; #X text 32 189 on socket; #X text 162 125 argument is port number; #X text 52 350 ***WARNING*** Attempting to print long messages can hang pd!; #X obj 55 290 spigot; #X obj 94 270 tgl 15 0 empty empty enable_print 17 7 0 10 -24198 -258699 -45076 0 1; #X text 54 333 Received messages are output as stream of bytes; #X msg 70 94 11 216 43; #X obj 304 288 spigot; #X obj 343 268 tgl 15 0 empty empty enable_print 17 7 0 10 -24198 -258699 -45076 0 1; #N canvas 3 45 768 526 getting.info 0; #X floatatom 99 162 5 0 0 0 - - -; #X text 139 163 to_client; #X floatatom 390 165 3 0 0 0 - - -; #X symbolatom 422 140 15 0 0 0 - - -; #X floatatom 359 189 5 0 0 0 - - -; #X floatatom 454 115 7 0 0 0 - - -; #X floatatom 180 117 5 0 0 0 - - -; #X text 223 118 on_socket; #X floatatom 139 141 5 0 0 0 - - -; #X obj 99 62 route sent; #X obj 359 61 route client; #X text 533 141 ip; #X text 505 115 port; #X text 416 165 socket; #X text 400 191 client; #X text 184 140 sent_bytes; #X floatatom 99 342 5 0 0 0 - - -; #X floatatom 180 297 5 0 0 0 - - -; #X floatatom 139 321 5 0 0 0 - - -; #X obj 99 242 route bufsize; #X floatatom 93 501 3 0 0 0 - - -; #X floatatom 147 501 3 0 0 0 - - -; #X floatatom 120 501 3 0 0 0 - - -; #X obj 93 421 route address; #X obj 99 271 unpack f f f; #X obj 359 87 unpack f f s f; #X obj 99 91 unpack f f f; #X obj 93 450 unpack f f f f f; #X floatatom 174 501 3 0 0 0 - - -; #X floatatom 202 475 6 0 0 0 - - -; #X text 200 501 ip; #X text 248 475 port; #X text 139 342 socket; #X text 178 322 insize (bytes); #X text 218 298 outsize (bytes); #X text 361 261 info about current inqueue/outqueue; #X text 354 435 NOTE: outlets #3 and #4 are for compatibility with mrpeach's net obects. You can get all information via outlet #5 as well; #X obj 99 36 r \$0.udpserver.o5; #X obj 99 216 r \$0.udpserver.o5; #X obj 93 395 r \$0.udpserver.o5; #X obj 359 35 r \$0.udpserver.o5; #X connect 9 0 26 0; #X connect 10 0 25 0; #X connect 19 0 24 0; #X connect 23 0 27 0; #X connect 24 0 16 0; #X connect 24 1 18 0; #X connect 24 2 17 0; #X connect 25 0 4 0; #X connect 25 1 2 0; #X connect 25 2 3 0; #X connect 25 3 5 0; #X connect 26 0 0 0; #X connect 26 1 8 0; #X connect 26 2 6 0; #X connect 27 0 20 0; #X connect 27 1 22 0; #X connect 27 2 21 0; #X connect 27 3 28 0; #X connect 27 4 29 0; #X connect 37 0 9 0; #X connect 38 0 19 0; #X connect 39 0 23 0; #X connect 40 0 10 0; #X restore 530 236 pd getting.info; #X text 523 306 copyright (c) 2009 Martin Peach; #X text 523 323 copyright (c) 2010 Roman Haefeli; #X text 523 340 copyright (c) 2010 IOhannes m zmoelnig; #X text 510 74 check also:; #X text 21 6 [udpserver] waits for clients to connect to its port. ; #X obj 55 126 udpserver 9997; #X obj 513 96 udpreceive; #X obj 513 121 udpclient; #X obj 150 153 s \$0.udpserver.o5; #X obj 304 243 r \$0.udpserver.o5; #X obj 126 216 unpack f f f f f; #X floatatom 235 240 6 0 0 0 - - -; #X obj 55 313 print udpserver:received; #X obj 304 314 print udpserver:status; #X text 145 94 or without 'broadcast' selector; #X connect 8 0 25 0; #X connect 13 0 32 0; #X connect 14 0 13 1; #X connect 16 0 25 0; #X connect 17 0 33 0; #X connect 18 0 17 1; #X connect 25 0 13 0; #X connect 25 1 0 0; #X connect 25 2 1 0; #X connect 25 3 30 0; #X connect 25 4 28 0; #X connect 29 0 17 0; #X connect 30 0 2 0; #X connect 30 1 3 0; #X connect 30 2 4 0; #X connect 30 3 5 0; #X connect 30 4 31 0; pd-iemnet-0.2.1/udpserver.c000066400000000000000000000574261257237665700156210ustar00rootroot00000000000000/* udpserver.c * * listens on a UDP-socket for bi-directional communication * * copyright © 2010-2015 IOhannes m zmölnig, IEM * copyright (c) 2006-2010 Martin Peach * copyright (c) 2004 Olaf Matthes */ /* */ /* A server for bidirectional communication from within Pd. */ /* Allows to send back data to specific clients connected to the server. */ /* */ /* This program is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation; either version 2 */ /* of the License, or (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, see */ /* http://www.gnu.org/licenses/ */ /* */ /* ---------------------------------------------------------------------------- */ #define DEBUGLEVEL 1 #include "iemnet.h" #include #include #include #define MAX_CONNECT 32 /* maximum number of connections */ /* ----------------------------- udpserver ------------------------- */ static t_class *udpserver_class; static const char objName[] = "udpserver"; typedef struct _udpserver_sender { struct _udpserver *sr_owner; long sr_host; unsigned short sr_port; int sr_fd; t_iemnet_sender*sr_sender; } t_udpserver_sender; typedef struct _udpserver { t_object x_obj; t_outlet*x_msgout; t_outlet*x_connectout; t_outlet*x_sockout; // legacy t_outlet*x_addrout; // legacy t_outlet*x_statout; t_udpserver_sender*x_sr[MAX_CONNECT]; /* socket per connection */ unsigned int x_nconnections; int x_connectsocket; /* socket waiting for new connections */ unsigned short x_port; unsigned char x_accept; /* whether we accept new connections or not */ /* the default connection to send to; 0=broadcast; >0 use this client; <0 exclude this client */ int x_defaulttarget; t_iemnet_receiver*x_receiver; t_iemnet_floatlist*x_floatlist; } t_udpserver; static t_udpserver_sender *udpserver_sender_new(t_udpserver *owner, unsigned long host, unsigned short port) { t_udpserver_sender *x = (t_udpserver_sender *)malloc(sizeof( t_udpserver_sender)); if(NULL==x) { iemnet_log(owner, IEMNET_FATAL, "unable to allocate %d bytes to create sender", (int)sizeof(*x)); return NULL; } else { int sockfd = owner->x_connectsocket; x->sr_owner=owner; x->sr_fd=sockfd; x->sr_host=host; //ntohl(addr->sin_addr.s_addr); x->sr_port=port; //ntohs(addr->sin_port); x->sr_sender=iemnet__sender_create(sockfd, NULL, NULL, 0); } return (x); } static void udpserver_sender_free(t_udpserver_sender *x) { DEBUG("freeing %x", x); if (x != NULL) { int sockfd=x->sr_fd; t_iemnet_sender*sender=x->sr_sender; x->sr_owner=NULL; x->sr_sender=NULL; x->sr_fd=-1; free(x); if(sender) { iemnet__sender_destroy(sender, 0); } if(sockfd>=0) { iemnet__closesocket(sockfd, 1); } } /* coverity[pass_freed_arg]: this is merely for debugging printout */ DEBUG("freed %x", x); } static t_udpserver_sender* udpserver_sender_copy(t_udpserver_sender*x) { return udpserver_sender_new(x->sr_owner,x->sr_host, x->sr_port); } static int udpserver_socket2index(t_udpserver*x, int sockfd) { unsigned int i=0; for(i = 0; i < x->x_nconnections; i++) { /* check if connection exists */ if(x->x_sr[i]->sr_fd == sockfd) { return i; } } return -1; } /* checks whether client is a valid (1-based) index * if the id is invalid, returns -1 * if the id is valid, return the 0-based index (client-1) */ static int udpserver_fixindex(t_udpserver*x, int client_) { unsigned int client; if(client_<1) { iemnet_log(x, IEMNET_ERROR, "client:%d out of range [1..%d]", client_, (int)(x->x_nconnections)); return -1; } client = (unsigned int)client_; if(x->x_nconnections <= 0) { iemnet_log(x, IEMNET_ERROR, "no clients connected"); return -1; } if (client > x->x_nconnections) { iemnet_log(x, IEMNET_ERROR, "client:%d out of range [1..%d]", client, (int)(x->x_nconnections)); return -1; } return (client-1); } /* returns 1 if addr1==addr2, 0 otherwise */ static int equal_addr(unsigned long host1, unsigned short port1, unsigned long host2, unsigned short port2) { return ( ((port1 == port2) && (host1 == host2)) ); } static int udpserver__find_sender(t_udpserver*x, unsigned long host, unsigned short port) { unsigned int i=0; for(i=0; ix_nconnections; i++) { if(NULL==x->x_sr[i]) { return -1; } if(equal_addr(host, port, x->x_sr[i]->sr_host, x->x_sr[i]->sr_port)) { return i; } } return -1; } /** * check whether the sender is already registered * if not, add it to the list of registered senders */ static t_udpserver_sender* udpserver_sender_add(t_udpserver*x, unsigned long host, unsigned short port ) { int id=-1; if(!x->x_accept) { return NULL; } id=udpserver__find_sender(x, host, port); DEBUG("%X:%d -> %d", host, port, id); if(id<0) { #if 1 /* since udp is a connection-less protocol we have no way of knowing the currently connected clients * the following 3 lines assume, that there is only one client connected (the last we got data from */ id=0; udpserver_sender_free(x->x_sr[id]); x->x_sr[id]=udpserver_sender_new(x, host, port); x->x_nconnections=1; #else /* this is a more optimistic approach as above: * every client that we received data from is added to the list of receivers * the idea is to remove the sender, if it's known to not receive any data */ id=x->x_nconnections; /* an unknown address! add it */ if(idx_sr[id]=udpserver_sender_new(x, host, port); DEBUG("new sender[%d]= %x", id, x->x_sr[id]); x->x_nconnections++; } else { // oops, no more senders! id=-1; } #endif } DEBUG("sender_add: %d", id); if(id>=0) { return x->x_sr[id]; } return NULL; } static void udpserver_sender_remove(t_udpserver*x, unsigned int id) { if(idx_nconnections && x->x_sr[id]) { unsigned int i; t_udpserver_sender* sdr=x->x_sr[id]; udpserver_sender_free(sdr); // close the gap by shifting the remaining connections to the left for(i=id; ix_nconnections; i++) { x->x_sr[id]=x->x_sr[id+1]; } x->x_sr[id]=NULL; x->x_nconnections--; } } /* ---------------- udpserver info ---------------------------- */ static void udpserver_info_client(t_udpserver *x, int client) { // "client " // "bufsize " static t_atom output_atom[4]; if(x&&clientx_sr[client]) { int sockfd = x->x_sr[client]->sr_fd; unsigned short port = x->x_sr[client]->sr_port; long address = x->x_sr[client]->sr_host; char hostname[MAXPDSTRING]; int insize =iemnet__receiver_getsize(x->x_receiver); int outsize=iemnet__sender_getsize (x->x_sr[client]->sr_sender ); snprintf(hostname, MAXPDSTRING-1, "%d.%d.%d.%d", (unsigned char)((address & 0xFF000000)>>24), (unsigned char)((address & 0x0FF0000)>>16), (unsigned char)((address & 0x0FF00)>>8), (unsigned char)((address & 0x0FF)) ); hostname[MAXPDSTRING-1]=0; SETFLOAT (output_atom+0, client+1); SETFLOAT (output_atom+1, sockfd); SETSYMBOL(output_atom+2, gensym(hostname)); SETFLOAT (output_atom+3, port); outlet_anything( x->x_statout, gensym("client"), 4, output_atom); SETFLOAT (output_atom+0, client+1); SETFLOAT (output_atom+1, insize); SETFLOAT (output_atom+2, outsize); outlet_anything( x->x_statout, gensym("bufsize"), 3, output_atom); } } static void udpserver_info(t_udpserver *x) { static t_atom output_atom[4]; int sockfd=x->x_connectsocket; int port=x->x_port; if(sockfd<0) { // no open port iemnet_log(x, IEMNET_ERROR, "no open socket"); } if(x->x_port<=0) { struct sockaddr_in server; socklen_t serversize=sizeof(server); memset(&server, 0, sizeof(server)); if(!getsockname(sockfd, (struct sockaddr *)&server, &serversize)) { x->x_port=ntohs(server.sin_port); port=x->x_port; } else { iemnet_log(x, IEMNET_ERROR, "getsockname failed for socket:%d", sockfd); sys_sockerror("getsockname"); } } SETFLOAT (output_atom+0, port); outlet_anything( x->x_statout, gensym("port"), 1, output_atom); } static void udpserver_info_connection(t_udpserver *x, t_udpserver_sender*y) { iemnet__addrout(x->x_statout, x->x_addrout, y->sr_host, y->sr_port); // outlet_float(x->x_sockout, y->sr_fd); } /* ---------------- main udpserver (send) stuff --------------------- */ static void udpserver_disconnect_socket(t_udpserver *x, t_floatarg fsocket); static void udpserver_send_bytes(t_udpserver*x, unsigned int client, t_iemnet_chunk*chunk) { DEBUG("send_bytes to %x -> %x[%d]", x, x->x_sr, client); if(clientx_sr[client]); } if(x && clientx_sr[client]) { t_atom output_atom[3]; int size=0; t_iemnet_sender*sender=x->x_sr[client]->sr_sender; int sockfd = x->x_sr[client]->sr_fd; chunk->addr=x->x_sr[client]->sr_host; chunk->port=x->x_sr[client]->sr_port; if(sender) { size=iemnet__sender_send(sender, chunk); } SETFLOAT(&output_atom[0], client+1); SETFLOAT(&output_atom[1], size); SETFLOAT(&output_atom[2], sockfd); outlet_anything( x->x_statout, gensym("sendbuffersize"), 3, output_atom); if(size<0) { // disconnected! udpserver_disconnect_socket(x, sockfd); } } } /* broadcasts a message to all connected clients but the given one */ static void udpserver_send_butclient(t_udpserver *x, unsigned int but, int argc, t_atom *argv) { unsigned int client=0; t_iemnet_chunk*chunk=iemnet__chunk_create_list(argc, argv); /* enumerate through the clients and send each the message */ for(client = 0; client < x->x_nconnections; client++) { /* check if connection exists */ /* socket exists for this client */ if(client!=but) { udpserver_send_bytes(x, client, chunk); } } iemnet__chunk_destroy(chunk); } /* sends a message to a given client */ static void udpserver_send_toclient(t_udpserver *x, unsigned int client, int argc, t_atom *argv) { t_iemnet_chunk*chunk=iemnet__chunk_create_list(argc, argv); udpserver_send_bytes(x, client, chunk); iemnet__chunk_destroy(chunk); } /* send message to client using client number note that the client numbers might change in case a client disconnects! */ /* clients start at 1 but our index starts at 0 */ static void udpserver_send_client(t_udpserver *x, t_symbol *s, int argc, t_atom *argv) { unsigned int client=0; if (argc > 0) { int c=udpserver_fixindex(x, atom_getint(argv)); if(c<0) { return; } client=(unsigned int)c; if(argc==1) { udpserver_info_client(x, client); } else { udpserver_send_toclient(x, client, argc-1, argv+1); } return; } else { for(client=0; clientx_nconnections; client++) { udpserver_info_client(x, client); } } } /* broadcasts a message to all connected clients */ static void udpserver_broadcast(t_udpserver *x, t_symbol *s, int argc, t_atom *argv) { unsigned int client; t_iemnet_chunk*chunk=iemnet__chunk_create_list(argc, argv); DEBUG("broadcasting to %d clients", x->x_nconnections); /* enumerate through the clients and send each the message */ for(client = 0; client < x->x_nconnections; client++) { /* check if connection exists */ /* socket exists for this client */ udpserver_send_bytes(x, client, chunk); } iemnet__chunk_destroy(chunk); } /* broadcasts a message to all connected clients */ static void udpserver_broadcastbut(t_udpserver *x, t_symbol *s, int argc, t_atom *argv) { int but; if(argc<2) { return; } if((but=udpserver_fixindex(x, atom_getint(argv)))<0) { return; } udpserver_send_butclient(x, but, argc-1, argv+1); } static void udpserver_defaultsend(t_udpserver *x, t_symbol *s, int argc, t_atom *argv) { int client=-1; int sockfd=x->x_defaulttarget; DEBUG("sending to sockfd: %d", sockfd); if(sockfd>0) { client=udpserver_socket2index(x, sockfd); if(client<0) { iemnet_log(x, IEMNET_ERROR, "invalid socket %d, switching to broadcast mode", sockfd); x->x_defaulttarget=0; } else { udpserver_send_toclient(x, client, argc, argv); return; } } else if(sockfd<0) { client=udpserver_socket2index(x, -sockfd); if(client<0) { iemnet_log(x, IEMNET_ERROR, "invalid excluded socket %d, switching to broadcast mode", -sockfd); x->x_defaulttarget=0; } else { udpserver_send_butclient(x, client, argc, argv); return; } } udpserver_broadcast(x, s, argc, argv); } static void udpserver_defaulttarget(t_udpserver *x, t_floatarg f) { int sockfd=0; int rawclient=f; unsigned int client=(rawclient<0)?(-rawclient):rawclient; if(client > x->x_nconnections) { iemnet_log(x, IEMNET_ERROR, "target:%d out of range [0..%d]", client, (int)(x->x_nconnections)); return; } // map the client to a persistant socket if(client>0) { sockfd=x->x_sr[client-1]->sr_fd; } if(rawclient<0) { sockfd=-sockfd; } x->x_defaulttarget=sockfd; } static void udpserver_targetsocket(t_udpserver *x, t_floatarg f) { int sockfd=f; x->x_defaulttarget=sockfd; } /* send message to client using socket number */ static void udpserver_send_socket(t_udpserver *x, t_symbol *s, int argc, t_atom *argv) { int client = -1; t_iemnet_chunk*chunk=NULL; if(argc) { client = udpserver_socket2index(x, atom_getint(argv)); if(client<0) { return; } } else { iemnet_log(x, IEMNET_ERROR, "no socket specified"); return; } /* get socket number of connection (first element in list) */ if(argc && argv->a_type == A_FLOAT) { int sockfd=atom_getint(argv); client = udpserver_socket2index(x, sockfd); if(client < 0) { iemnet_log(x, IEMNET_ERROR, "no connection on socket:%d", sockfd); return; } } else { iemnet_log(x, IEMNET_ERROR, "no socket specified"); return; } chunk=iemnet__chunk_create_list(argc-1, argv+1); udpserver_send_bytes(x, client, chunk); iemnet__chunk_destroy(chunk); } static void udpserver_disconnect(t_udpserver *x, unsigned int client) { t_udpserver_sender*sdr=NULL; int conns; DEBUG("disconnect %x %d", x, client); if(client >= x->x_nconnections) { return; } sdr = (t_udpserver_sender *)calloc(1, sizeof(t_udpserver_sender)); if(sdr) { sdr->sr_host=x->x_sr[client]->sr_host; sdr->sr_port=x->x_sr[client]->sr_port; } udpserver_sender_remove(x, client); conns=x->x_nconnections; if(sdr) { udpserver_info_connection(x, sdr); free(sdr); } outlet_float(x->x_connectout, conns); } /* disconnect a client by number */ static void udpserver_disconnect_client(t_udpserver *x, t_floatarg fclient) { int client = udpserver_fixindex(x, fclient); if(client<0) { return; } udpserver_disconnect(x, client); } /* disconnect a client by socket */ static void udpserver_disconnect_socket(t_udpserver *x, t_floatarg fsocket) { int id=udpserver_socket2index(x, (int)fsocket); if(id>=0) { udpserver_disconnect_client(x, id+1); } } /* disconnect a client by socket */ static void udpserver_disconnect_all(t_udpserver *x) { unsigned int id; for(id=0; idx_nconnections; id++) { udpserver_disconnect(x, id); } } /* whether we should accept new connections */ static void udpserver_accept(t_udpserver *x, t_float f) { x->x_accept=(unsigned char)f; } /* ---------------- main udpserver (receive) stuff --------------------- */ static void udpserver_receive_callback(void *y, t_iemnet_chunk*c) { t_udpserver*x=(t_udpserver*)y; if(NULL==y) { return; } if(c) { unsigned int conns = x->x_nconnections; t_udpserver_sender*sdr=NULL; DEBUG("add new sender from %d", c->port); sdr=udpserver_sender_add(x, c->addr, c->port); DEBUG("added new sender from %d", c->port); if(sdr) { udpserver_info_connection(x, sdr); x->x_floatlist=iemnet__chunk2list(c, x->x_floatlist); // gets destroyed in the dtor /* here we might have a reentrancy problem */ if(conns!=x->x_nconnections) { outlet_float(x->x_connectout, x->x_nconnections); } outlet_list(x->x_msgout, gensym("list"), x->x_floatlist->argc, x->x_floatlist->argv); } } else { // disconnection never happens with a connectionless protocol like UDP iemnet_log(x, IEMNET_ERROR, "received disconnection event"); } } // this get's never called static void udpserver_connectpoll(t_udpserver *x) { struct sockaddr_in incomer_address; socklen_t sockaddrl = sizeof( struct sockaddr ); int fd = -1; int i; // TODO: provide a way to not accept connection // idea: add a message "accept $1" to turn off/on acceptance of new connections fd = accept(x->x_connectsocket, (struct sockaddr*)&incomer_address, &sockaddrl); bug("connectpoll"); if (fd < 0) { error("[%s] accept failed", objName); } else { unsigned long host = ntohl(incomer_address.sin_addr.s_addr); unsigned short port = ntohs(incomer_address.sin_port); t_udpserver_sender *y = udpserver_sender_new(x, host, port); if (!y) { iemnet__closesocket(fd, 1); return; } x->x_nconnections++; i = x->x_nconnections - 1; x->x_sr[i] = y; udpserver_info_connection(x, y); } outlet_float(x->x_connectout, x->x_nconnections); } static void udpserver_port(t_udpserver*x, t_floatarg fportno) { static t_atom ap[1]; int portno = fportno; struct sockaddr_in server; socklen_t serversize=sizeof(server); int sockfd = x->x_connectsocket; memset(&server, 0, sizeof(server)); SETFLOAT(ap, -1); if(x->x_port == portno) { return; } /* cleanup any open ports */ if(sockfd>=0) { //sys_rmpollfn(sockfd); iemnet__closesocket(sockfd, 0); x->x_connectsocket=-1; x->x_port=-1; } sockfd = socket(AF_INET, SOCK_DGRAM, 0); if(sockfd<0) { iemnet_log(x, IEMNET_ERROR, "unable to create socket"); sys_sockerror("socket"); return; } server.sin_family = AF_INET; /* LATER allow setting of inaddr */ server.sin_addr.s_addr = INADDR_ANY; /* assign server port number */ server.sin_port = htons((u_short)portno); /* name the socket */ if (bind(sockfd, (struct sockaddr *)&server, serversize) < 0) { iemnet_log(x, IEMNET_ERROR, "unable to bind to socket"); sys_sockerror("bind"); iemnet__closesocket(sockfd, 1); outlet_anything(x->x_statout, gensym("port"), 1, ap); return; } x->x_receiver=iemnet__receiver_create(sockfd, x, udpserver_receive_callback, 0); x->x_connectsocket = sockfd; x->x_port = portno; // find out which port is actually used (useful when assigning "0") if(!getsockname(sockfd, (struct sockaddr *)&server, &serversize)) { x->x_port=ntohs(server.sin_port); } SETFLOAT(ap, x->x_port); outlet_anything(x->x_statout, gensym("port"), 1, ap); } static void *udpserver_new(t_floatarg fportno) { t_udpserver *x; int i; x = (t_udpserver *)pd_new(udpserver_class); x->x_msgout = outlet_new(&x->x_obj, 0); /* 1st outlet for received data */ x->x_connectout = outlet_new(&x->x_obj, gensym("float")); /* 2nd outlet for number of connected clients */ x->x_sockout = outlet_new(&x->x_obj, gensym("float")); x->x_addrout = outlet_new(&x->x_obj, gensym("list" )); /* 5th outlet for everything else */ x->x_statout = outlet_new(&x->x_obj, 0); x->x_connectsocket = -1; x->x_port = -1; x->x_nconnections = 0; for(i = 0; i < MAX_CONNECT; i++) { x->x_sr[i] = NULL; } x->x_defaulttarget=0; x->x_floatlist=iemnet__floatlist_create(1024); udpserver_port(x, fportno); x->x_accept=1; return (x); } static void udpserver_free(t_udpserver *x) { int i; for(i = 0; i < MAX_CONNECT; i++) { if (NULL!=x->x_sr[i]) { DEBUG("[%s] free %x", objName, x); udpserver_sender_free(x->x_sr[i]); x->x_sr[i]=NULL; } } if(x->x_receiver) { iemnet__receiver_destroy(x->x_receiver, 0); x->x_receiver=NULL; } if (x->x_connectsocket >= 0) { iemnet__closesocket(x->x_connectsocket, 0); x->x_connectsocket = -1; } if(x->x_floatlist) { iemnet__floatlist_destroy(x->x_floatlist); x->x_floatlist=NULL; } } IEMNET_EXTERN void udpserver_setup(void) { if(!iemnet__register(objName)) { return; } error("[%s] does not work yet", objName); udpserver_class = class_new(gensym(objName),(t_newmethod)udpserver_new, (t_method)udpserver_free, sizeof(t_udpserver), 0, A_DEFFLOAT, 0); class_addmethod(udpserver_class, (t_method)udpserver_disconnect_client, gensym("disconnectclient"), A_DEFFLOAT, 0); class_addmethod(udpserver_class, (t_method)udpserver_disconnect_socket, gensym("disconnectsocket"), A_DEFFLOAT, 0); class_addmethod(udpserver_class, (t_method)udpserver_disconnect_all, gensym("disconnect"), 0); class_addmethod(udpserver_class, (t_method)udpserver_accept, gensym("accept"), A_FLOAT, 0); class_addmethod(udpserver_class, (t_method)udpserver_send_socket, gensym("send"), A_GIMME, 0); class_addmethod(udpserver_class, (t_method)udpserver_send_client, gensym("client"), A_GIMME, 0); class_addmethod(udpserver_class, (t_method)udpserver_broadcast, gensym("broadcast"), A_GIMME, 0); class_addmethod(udpserver_class, (t_method)udpserver_defaulttarget, gensym("target"), A_DEFFLOAT, 0); class_addmethod(udpserver_class, (t_method)udpserver_targetsocket, gensym("targetsocket"), A_DEFFLOAT, 0); class_addlist (udpserver_class, (t_method)udpserver_defaultsend); class_addmethod(udpserver_class, (t_method)udpserver_port, gensym("port"), A_DEFFLOAT, 0); class_addbang (udpserver_class, (t_method)udpserver_info); DEBUGMETHOD(udpserver_class); } IEMNET_INITIALIZER(udpserver_setup); /* end of udpserver.c */ pd-iemnet-0.2.1/udpsndrcv-help.pd000066400000000000000000000034571257237665700167140ustar00rootroot00000000000000#N canvas 247 75 632 526 10; #X obj 72 255 udpsndrcv; #X msg 72 148 connect localhost 12345 54321; #X obj 382 255 udpsndrcv; #X obj 72 360 print A:connected?; #X obj 102 329 print A:data; #X obj 132 300 print A:status; #X obj 442 300 print B:status; #X obj 412 329 print B:data; #X obj 382 357 print B:connected?; #X msg 86 171 send 10 20 30 40; #X msg 91 196 disconnect; #X msg 114 224 status; #X msg 401 196 disconnect; #X msg 424 224 status; #X msg 382 148 connect localhost 54321 12345; #X msg 396 171 send 50 40 30 20 10; #X text 80 26 [udpsndrcv] bi-directional communication; #X text 74 59 this is an abstraction around [udpclient] for compatibility with mrpeach/net's object of the same name.; #N canvas 4 78 530 417 sending/receiving 0; #X obj 142 275 udpsndrcv; #X msg 161 216 disconnect; #X msg 184 244 status; #X msg 142 168 connect localhost 55555 55555; #X msg 156 191 send 5 5 5; #X obj 202 320 print C:status; #X obj 172 349 print C:data; #X obj 142 377 print C:connected?; #X text 52 58 when using the same port for sending and receiving \, you must talk with real remote host (NOT localhost).; #X text 55 88 else you will simply be talking to yourself...; #X text 156 146 talk to yourself.; #X connect 0 0 7 0; #X connect 0 1 6 0; #X connect 0 2 5 0; #X connect 1 0 0 0; #X connect 2 0 0 0; #X connect 3 0 0 0; #X connect 4 0 0 0; #X restore 172 492 pd sending/receiving on the same port; #X text 86 394 send to port:12345; #X text 72 409 listen on port:54321; #X text 396 394 send to port:54321; #X text 382 409 listen on port:12345; #X connect 0 0 3 0; #X connect 0 1 4 0; #X connect 0 2 5 0; #X connect 1 0 0 0; #X connect 2 0 8 0; #X connect 2 1 7 0; #X connect 2 2 6 0; #X connect 9 0 0 0; #X connect 10 0 0 0; #X connect 11 0 0 0; #X connect 12 0 2 0; #X connect 13 0 2 0; #X connect 14 0 2 0; #X connect 15 0 2 0; pd-iemnet-0.2.1/udpsndrcv.pd000066400000000000000000000030751257237665700157620ustar00rootroot00000000000000#N canvas 512 227 613 300 10; #X obj 60 73 inlet; #X obj 116 174 udpclient; #X obj 43 249 outlet conn?; #X obj 145 258 outlet data; #X obj 260 270 outlet status; #X obj 60 105 t a a; #X obj 60 127 route status; #X obj 216 65 route connect disconnect; #X obj 116 196 t l l; #N canvas 5 49 450 300 received 0; #X obj 101 65 inlet; #X obj 101 87 list length; #X obj 101 131 delay 0; #X obj 190 172 +; #X obj 190 194 t f f; #X obj 130 223 f; #X obj 130 195 t b f; #X msg 101 153 0; #X obj 101 109 t b f f; #X obj 130 275 outlet received; #X msg 130 245 received \$1; #X obj 350 172 +; #X obj 350 194 t f f; #X obj 290 223 f; #X obj 236 54 inlet; #X msg 290 245 total \$1; #X obj 236 76 route bang reset; #X msg 290 112 0; #X connect 0 0 1 0; #X connect 1 0 8 0; #X connect 2 0 7 0; #X connect 3 0 4 0; #X connect 4 0 5 1; #X connect 4 1 3 1; #X connect 5 0 10 0; #X connect 6 0 5 0; #X connect 6 1 3 1; #X connect 7 0 6 0; #X connect 8 0 2 0; #X connect 8 1 3 0; #X connect 8 2 11 0; #X connect 10 0 9 0; #X connect 11 0 12 0; #X connect 12 0 13 1; #X connect 12 1 11 1; #X connect 13 0 15 0; #X connect 14 0 16 0; #X connect 15 0 9 0; #X connect 16 0 13 0; #X connect 16 1 17 0; #X connect 17 0 12 0; #X restore 260 241 pd received; #X obj 60 149 t b; #X obj 216 90 t b; #X msg 216 112 reset; #X connect 0 0 5 0; #X connect 1 0 8 0; #X connect 1 2 2 0; #X connect 5 0 6 0; #X connect 5 1 7 0; #X connect 6 0 10 0; #X connect 6 1 1 0; #X connect 7 0 11 0; #X connect 7 1 11 0; #X connect 8 0 3 0; #X connect 8 1 9 0; #X connect 9 0 4 0; #X connect 10 0 9 1; #X connect 11 0 12 0; #X connect 12 0 9 1;