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

pnpipe.cxx (5682B)


      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 <windows.h>
     14 #else
     15 #  include <sys/types.h>
     16 #  include <sys/socket.h>
     17 #  include <sys/un.h>
     18 #endif
     19 
     20 #include "pstreams.h"
     21 
     22 
     23 namespace ptypes {
     24 
     25 
     26 #ifdef WIN32
     27 
     28 string ptdecl namedpipe::realpipename(const string& pipename, const string& svrname)
     29 {
     30     if (isempty(pipename))
     31         return nullstring;
     32     string realname = pipename;
     33     if (*pconst(pipename) == '/')
     34     {
     35         int i = rpos('/', realname);
     36         del(realname, 0, i + 1);
     37     }
     38     string s;
     39     if (isempty(svrname))
     40         s = '.';
     41     else
     42         s = svrname;
     43     return "\\\\" + s + "\\pipe\\" + realname;
     44 }
     45 
     46 
     47 #else
     48 
     49 string ptdecl namedpipe::realpipename(const string& pipename)
     50 {
     51     if (isempty(pipename))
     52         return nullstring;
     53     if (*pconst(pipename) == '/')
     54         return pipename;
     55     else
     56         return DEF_NAMED_PIPES_DIR + pipename;
     57 }
     58 
     59 
     60 bool namedpipe::setupsockaddr(const string& pipename, void* isa)
     61 {
     62     sockaddr_un* sa = (sockaddr_un*)isa;
     63     memset(sa, 0, sizeof(sockaddr_un));
     64     sa->sun_family = AF_UNIX;
     65 #ifdef __FreeBSD__
     66     sa->sun_len = length(pipename);
     67 #endif
     68 
     69     // copy the path name into the sockaddr structure, 108 chars max (?)
     70     if (length(pipename) + 1 > (int)sizeof(sa->sun_path))
     71         return false;
     72     strcpy(sa->sun_path, pipename);
     73     return true;
     74 }
     75 
     76 #endif
     77 
     78 
     79 namedpipe::namedpipe()
     80     : fdxstm(), pipename(), svhandle(invhandle)
     81 {
     82     initovr();
     83 }
     84 
     85 
     86 namedpipe::namedpipe(const string& ipipename)
     87     : fdxstm(), pipename(), svhandle(invhandle)
     88 {
     89     pipename = realpipename(ipipename);
     90     initovr();
     91 }
     92 
     93 
     94 #ifdef WIN32
     95 
     96 namedpipe::namedpipe(const string& ipipename, const string& servername)
     97     : fdxstm(), pipename(), svhandle(invhandle)
     98 {
     99     pipename = realpipename(ipipename, servername);
    100     initovr();
    101 }
    102 
    103 
    104 void namedpipe::initovr()
    105 {
    106     ovr.hEvent = CreateEvent(0, false, false, 0);
    107 }
    108 
    109 
    110 #endif
    111 
    112 
    113 namedpipe::~namedpipe()
    114 {
    115     cancel();
    116 #ifdef WIN32
    117     CloseHandle(ovr.hEvent);
    118 #endif
    119 }
    120 
    121 
    122 int namedpipe::classid()
    123 {
    124     return CLASS3_NPIPE;
    125 }
    126 
    127 
    128 string namedpipe::get_streamname()
    129 {
    130     return pipename;
    131 }
    132 
    133 
    134 void namedpipe::set_pipename(const string& newvalue)
    135 {
    136     close();
    137     pipename = realpipename(newvalue);
    138 }
    139 
    140 
    141 void namedpipe::set_pipename(const char* newvalue)
    142 {
    143     close();
    144     pipename = realpipename(newvalue);
    145 }
    146 
    147 
    148 large namedpipe::doseek(large, ioseekmode)
    149 {
    150     return -1;
    151 }
    152 
    153 
    154 void namedpipe::doopen()
    155 {
    156 
    157 #ifdef WIN32
    158 
    159     if (svhandle != invhandle)
    160         handle = svhandle;
    161     else
    162     {
    163         int tries = DEF_PIPE_OPEN_RETRY;
    164         int delay = DEF_PIPE_OPEN_TIMEOUT / 2;
    165 retry:
    166         SECURITY_ATTRIBUTES sa;
    167         sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    168         sa.lpSecurityDescriptor = NULL;
    169         sa.bInheritHandle = TRUE;
    170 
    171         handle = int(CreateFileA(pipename, GENERIC_READ | GENERIC_WRITE,
    172             0, &sa, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0));
    173         if (handle == invhandle)
    174         {
    175             if (GetLastError() == ERROR_PIPE_BUSY)
    176             {
    177                 if (--tries > 0)
    178                 {
    179                     delay *= 2;
    180                     Sleep(delay);
    181                     goto retry;
    182                 }
    183                 else
    184                     error(EIO, "Pipe busy");
    185             }
    186             else
    187                 error(uerrno(), "Couldn't open named pipe");
    188         }
    189     }
    190 
    191 #else
    192     if (svhandle != invhandle)
    193     {
    194 	if ((handle = ::accept(svhandle, 0, 0)) < 0)
    195 	    error(uerrno(), "Couldn't create local socket");
    196     }
    197     
    198     else
    199     {
    200         sockaddr_un sa;
    201 	if (!setupsockaddr(pipename, &sa))
    202     	    error(ERANGE, "Socket name too long");
    203 
    204         // cteate a client socket
    205 	if ((handle = ::socket(sa.sun_family, SOCK_STREAM, 0)) < 0)
    206     	    error(uerrno(), "Couldn't create local socket");
    207 
    208         // ... and connect to the local socket
    209 	if (::connect(handle, (sockaddr*)&sa, sizeof(sa)) < 0)
    210 	{
    211     	    int e = uerrno();
    212             doclose();
    213 	    error(e, "Couldn't connect to local socket");
    214         }
    215     }
    216 
    217 #endif
    218 }
    219 
    220 
    221 #ifdef WIN32
    222 
    223 int namedpipe::dorawread(char* buf, int count)
    224 {
    225     unsigned long ret = uint(-1);
    226     ovr.Offset = 0;
    227     ovr.OffsetHigh = 0;
    228     if (!ReadFile(HANDLE(handle), buf, count, &ret, &ovr)) 
    229     {
    230         if (GetLastError() == ERROR_IO_PENDING)
    231         {
    232             if (WaitForSingleObject(ovr.hEvent, DEF_PIPE_TIMEOUT) == WAIT_TIMEOUT)
    233                 error(EIO, "Timed out");
    234             if (!GetOverlappedResult(HANDLE(handle), &ovr, &ret, false))
    235                 error(uerrno(), "Couldn't read");
    236         }
    237         else
    238             error(uerrno(), "Couldn't read");
    239     }
    240     return ret;
    241 }
    242 
    243 
    244 int namedpipe::dorawwrite(const char* buf, int count)
    245 {
    246     unsigned long ret = uint(-1);
    247     ovr.Offset = 0;
    248     ovr.OffsetHigh = 0;
    249     if (!WriteFile(HANDLE(handle), buf, count, &ret, &ovr))
    250     {
    251         if (GetLastError() == ERROR_IO_PENDING)
    252         {
    253             if (WaitForSingleObject(ovr.hEvent, DEF_PIPE_TIMEOUT) == WAIT_TIMEOUT)
    254                 error(EIO, "Timed out");
    255             if (!GetOverlappedResult(HANDLE(handle), &ovr, &ret, false))
    256                 error(uerrno(), "Couldn't write");
    257         }
    258         else
    259             error(uerrno(), "Couldn't write");
    260     }
    261     return ret;
    262 }
    263 
    264 
    265 #endif
    266 
    267 
    268 void namedpipe::doclose()
    269 {
    270 #ifdef WIN32
    271     if (svhandle != invhandle)
    272         DisconnectNamedPipe(HANDLE(handle)); 
    273 #endif
    274     svhandle = invhandle;
    275     fdxstm::doclose();
    276 }
    277 
    278 
    279 void namedpipe::flush()
    280 {
    281 #ifdef WIN32
    282     if (!cancelled)
    283         FlushFileBuffers(HANDLE(handle));
    284 #endif
    285     fdxstm::flush();
    286 }
    287 
    288 
    289 
    290 }