gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

pipmsgsv.cxx (2792B)


      1 /*
      2  *
      3  *  C++ Portable Types Library (PTypes)
      4  *  Version 2.1.1  Released 27-Jun-2007
      5  *
      6  *  Copyright (C) 2001-2007 Hovik Melikyan
      7  *
      8  *  http://www.melikyan.com/ptypes/
      9  *
     10  */
     11 
     12 #ifdef WIN32
     13 #  include <winsock2.h>
     14 #else
     15 #  include <sys/time.h>
     16 #  include <sys/types.h>
     17 #  include <sys/socket.h>
     18 #  include <netinet/in.h>
     19 #  include <arpa/inet.h>
     20 #  include <netdb.h>
     21 #  include <unistd.h>
     22 #  include <time.h>
     23 #endif
     24 
     25 
     26 #include "pinet.h"
     27 
     28 
     29 namespace ptypes {
     30 
     31 
     32 //
     33 // ipmsgserver: IPv4 UDP socket server
     34 //
     35 
     36 
     37 ipmsgserver::ipmsgserver()
     38     : ipsvbase(SOCK_DGRAM), ippeerinfo(), handle(invhandle)
     39 {
     40 }
     41 
     42 
     43 ipmsgserver::~ipmsgserver()
     44 {
     45     close();
     46 }
     47 
     48 
     49 void ipmsgserver::dobind(ipbindinfo* b)
     50 {
     51     sockaddr_in sa;
     52     memset(&sa, 0, sizeof(sa));
     53     sa.sin_family = AF_INET;
     54     sa.sin_port = htons(ushort(b->get_port()));
     55     sa.sin_addr.s_addr = b->get_ip();
     56     if (::bind(b->handle, (sockaddr*)&sa, sizeof(sa)) != 0)
     57         error(*b, usockerrno(), "Couldn't bind address");
     58 }
     59 
     60 
     61 void ipmsgserver::close()
     62 {
     63     if (!active)
     64         return;
     65     ipsvbase::close();
     66     handle = invhandle;
     67     ippeerinfo::clear();
     68 }
     69 
     70 
     71 bool ipmsgserver::poll(int i, int timeout)
     72 {
     73     if (!active)
     74         open();
     75     return dopoll(&i, timeout);
     76 }
     77 
     78 
     79 int ipmsgserver::receive(char* buf, int count)
     80 {
     81     if (!active)
     82         open();
     83     ippeerinfo::clear();
     84 
     85     // determine which socket has pending data
     86     int i = -1;
     87     if (!dopoll(&i, -1))
     88         error(*this, EINVAL, "Couldn't read");
     89     ipbindinfo* b = (ipbindinfo*)addrlist[i];
     90     handle = b->handle;
     91 
     92     // read data
     93     sockaddr_in sa;
     94     psocklen len = sizeof(sa);
     95     int result = ::recvfrom(handle, buf, count, 0, (sockaddr*)&sa, &len);
     96     if (result < 0)
     97         error(*b, usockerrno(), "Couldn't read");
     98 
     99     // set up peer ip and port
    100     ip = sa.sin_addr.s_addr;
    101     port = ntohs(sa.sin_port);
    102     return result;
    103 }
    104 
    105 
    106 string ipmsgserver::receive(int max)
    107 {
    108     string result;
    109     setlength(result, max);
    110     int numread = receive(pchar(pconst(result)), max);
    111     setlength(result, numread);
    112     return result;
    113 }
    114 
    115 
    116 void ipmsgserver::send(const char* buf, int count)
    117 {
    118     if (!active || handle == invhandle || ip == ipnone)
    119         error(*this, EINVAL, "Couldn't write");  // must receive() first
    120 
    121     sendto(buf, count, get_ip(), get_port());
    122 }
    123 
    124 
    125 void ipmsgserver::sendto(const char* buf, int count, ipaddress ip, int port)
    126 {
    127     if (!active || handle == invhandle || ip == ipnone)
    128         error(*this, EINVAL, "Couldn't write");  // must receive() first
    129 
    130     sockaddr_in sa;
    131     memset(&sa, 0, sizeof(sa));
    132     sa.sin_family = AF_INET;
    133     sa.sin_port = htons(ushort(port));
    134     sa.sin_addr.s_addr = ip;
    135     if (::sendto(handle, buf, count, 0, (sockaddr*)&sa, sizeof(sa)) < 0)
    136         error(*this, usockerrno(), "Couldn't write");
    137 }
    138 
    139 
    140 }