xref: /petsc/src/sys/classes/viewer/impls/socket/send.c (revision 8556b5eb6d24048282742bdd6ce397a5c8264fe5)
15c6c1daeSBarry Smith 
25c6c1daeSBarry Smith #include <petscsys.h>
35c6c1daeSBarry Smith 
45c6c1daeSBarry Smith #if defined(PETSC_NEEDS_UTYPE_TYPEDEFS)
55c6c1daeSBarry Smith /* Some systems have inconsistent include files that use but do not
65c6c1daeSBarry Smith    ensure that the following definitions are made */
75c6c1daeSBarry Smith typedef unsigned char   u_char;
85c6c1daeSBarry Smith typedef unsigned short  u_short;
95c6c1daeSBarry Smith typedef unsigned short  ushort;
105c6c1daeSBarry Smith typedef unsigned int    u_int;
115c6c1daeSBarry Smith typedef unsigned long   u_long;
125c6c1daeSBarry Smith #endif
135c6c1daeSBarry Smith 
145c6c1daeSBarry Smith #include <errno.h>
155c6c1daeSBarry Smith #include <ctype.h>
165c6c1daeSBarry Smith #if defined(PETSC_HAVE_MACHINE_ENDIAN_H)
175c6c1daeSBarry Smith #include <machine/endian.h>
185c6c1daeSBarry Smith #endif
195c6c1daeSBarry Smith #if defined(PETSC_HAVE_UNISTD_H)
205c6c1daeSBarry Smith #include <unistd.h>
215c6c1daeSBarry Smith #endif
225c6c1daeSBarry Smith #if defined(PETSC_HAVE_SYS_SOCKET_H)
235c6c1daeSBarry Smith #include <sys/socket.h>
245c6c1daeSBarry Smith #endif
255c6c1daeSBarry Smith #if defined(PETSC_HAVE_SYS_WAIT_H)
265c6c1daeSBarry Smith #include <sys/wait.h>
275c6c1daeSBarry Smith #endif
285c6c1daeSBarry Smith #if defined(PETSC_HAVE_NETINET_IN_H)
295c6c1daeSBarry Smith #include <netinet/in.h>
305c6c1daeSBarry Smith #endif
315c6c1daeSBarry Smith #if defined(PETSC_HAVE_NETDB_H)
325c6c1daeSBarry Smith #include <netdb.h>
335c6c1daeSBarry Smith #endif
345c6c1daeSBarry Smith #if defined(PETSC_HAVE_FCNTL_H)
355c6c1daeSBarry Smith #include <fcntl.h>
365c6c1daeSBarry Smith #endif
375c6c1daeSBarry Smith #if defined(PETSC_HAVE_IO_H)
385c6c1daeSBarry Smith #include <io.h>
395c6c1daeSBarry Smith #endif
405c6c1daeSBarry Smith #if defined(PETSC_HAVE_WINSOCK2_H)
415c6c1daeSBarry Smith #include <Winsock2.h>
425c6c1daeSBarry Smith #endif
435c6c1daeSBarry Smith #include <sys/stat.h>
445c6c1daeSBarry Smith #include <../src/sys/classes/viewer/impls/socket/socket.h>
455c6c1daeSBarry Smith 
465c6c1daeSBarry Smith #if defined(PETSC_NEED_CLOSE_PROTO)
478cc058d9SJed Brown PETSC_EXTERN int close(int);
485c6c1daeSBarry Smith #endif
495c6c1daeSBarry Smith #if defined(PETSC_NEED_SOCKET_PROTO)
508cc058d9SJed Brown PETSC_EXTERN int socket(int,int,int);
515c6c1daeSBarry Smith #endif
525c6c1daeSBarry Smith #if defined(PETSC_NEED_SLEEP_PROTO)
538cc058d9SJed Brown PETSC_EXTERN int sleep(unsigned);
545c6c1daeSBarry Smith #endif
555c6c1daeSBarry Smith #if defined(PETSC_NEED_CONNECT_PROTO)
568cc058d9SJed Brown PETSC_EXTERN int connect(int,struct sockaddr*,int);
575c6c1daeSBarry Smith #endif
585c6c1daeSBarry Smith 
595c6c1daeSBarry Smith /*--------------------------------------------------------------*/
605c6c1daeSBarry Smith #undef __FUNCT__
615c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerDestroy_Socket"
625c6c1daeSBarry Smith static PetscErrorCode PetscViewerDestroy_Socket(PetscViewer viewer)
635c6c1daeSBarry Smith {
645c6c1daeSBarry Smith   PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)viewer->data;
655c6c1daeSBarry Smith   PetscErrorCode     ierr;
665c6c1daeSBarry Smith 
675c6c1daeSBarry Smith   PetscFunctionBegin;
685c6c1daeSBarry Smith   if (vmatlab->port) {
695c6c1daeSBarry Smith #if defined(PETSC_HAVE_CLOSESOCKET)
705c6c1daeSBarry Smith     ierr = closesocket(vmatlab->port);
715c6c1daeSBarry Smith #else
725c6c1daeSBarry Smith     ierr = close(vmatlab->port);
735c6c1daeSBarry Smith #endif
745c6c1daeSBarry Smith     if (ierr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"System error closing socket");
755c6c1daeSBarry Smith   }
765c6c1daeSBarry Smith   ierr = PetscFree(vmatlab);CHKERRQ(ierr);
775c6c1daeSBarry Smith   PetscFunctionReturn(0);
785c6c1daeSBarry Smith }
795c6c1daeSBarry Smith 
805c6c1daeSBarry Smith /*--------------------------------------------------------------*/
815c6c1daeSBarry Smith #undef __FUNCT__
825c6c1daeSBarry Smith #define __FUNCT__ "PetscOpenSocket"
835c6c1daeSBarry Smith /*
845c6c1daeSBarry Smith     PetscSocketOpen - handles connected to an open port where someone is waiting.
855c6c1daeSBarry Smith 
865c6c1daeSBarry Smith .seealso:   PetscSocketListen(), PetscSocketEstablish()
875c6c1daeSBarry Smith */
88e2fc02c1SBarry Smith PetscErrorCode  PetscOpenSocket(const char hostname[],int portnum,int *t)
895c6c1daeSBarry Smith {
905c6c1daeSBarry Smith   struct sockaddr_in sa;
915c6c1daeSBarry Smith   struct hostent     *hp;
925c6c1daeSBarry Smith   int                s = 0;
935c6c1daeSBarry Smith   PetscErrorCode     ierr;
945c6c1daeSBarry Smith   PetscBool          flg = PETSC_TRUE;
954a285bdaSBarry Smith   static int         refcnt = 0;
965c6c1daeSBarry Smith 
975c6c1daeSBarry Smith   PetscFunctionBegin;
985c6c1daeSBarry Smith   if (!(hp=gethostbyname(hostname))) {
995c6c1daeSBarry Smith     perror("SEND: error gethostbyname: ");
1005c6c1daeSBarry Smith     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error open connection to %s",hostname);
1015c6c1daeSBarry Smith   }
1025c6c1daeSBarry Smith   ierr = PetscMemzero(&sa,sizeof(sa));CHKERRQ(ierr);
1035c6c1daeSBarry Smith   ierr = PetscMemcpy(&sa.sin_addr,hp->h_addr_list[0],hp->h_length);CHKERRQ(ierr);
1045c6c1daeSBarry Smith 
1055c6c1daeSBarry Smith   sa.sin_family = hp->h_addrtype;
1065c6c1daeSBarry Smith   sa.sin_port   = htons((u_short) portnum);
1075c6c1daeSBarry Smith   while (flg) {
1085c6c1daeSBarry Smith     if ((s=socket(hp->h_addrtype,SOCK_STREAM,0)) < 0) {
1095c6c1daeSBarry Smith       perror("SEND: error socket");  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error");
1105c6c1daeSBarry Smith     }
1115c6c1daeSBarry Smith     if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
1125c6c1daeSBarry Smith #if defined(PETSC_HAVE_WSAGETLASTERROR)
1135c6c1daeSBarry Smith       ierr = WSAGetLastError();
114a297a907SKarl Rupp       if (ierr == WSAEADDRINUSE)    (*PetscErrorPrintf)("SEND: address is in use\n");
115a297a907SKarl Rupp       else if (ierr == WSAEALREADY) (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
116a297a907SKarl Rupp       else if (ierr == WSAEISCONN) {
1175c6c1daeSBarry Smith         (*PetscErrorPrintf)("SEND: socket already connected\n");
1185c6c1daeSBarry Smith         Sleep((unsigned) 1);
1195c6c1daeSBarry Smith       } else if (ierr == WSAECONNREFUSED) {
1205c6c1daeSBarry Smith         /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */
1215c6c1daeSBarry Smith         Sleep((unsigned) 1);
1225c6c1daeSBarry Smith       } else {
1235c6c1daeSBarry Smith         perror(NULL); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error");
1245c6c1daeSBarry Smith       }
1255c6c1daeSBarry Smith #else
126a297a907SKarl Rupp       if (errno == EADDRINUSE)    (*PetscErrorPrintf)("SEND: address is in use\n");
127a297a907SKarl Rupp       else if (errno == EALREADY) (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
128a297a907SKarl Rupp       else if (errno == EISCONN) {
1295c6c1daeSBarry Smith         (*PetscErrorPrintf)("SEND: socket already connected\n");
1305c6c1daeSBarry Smith         sleep((unsigned) 1);
1315c6c1daeSBarry Smith       } else if (errno == ECONNREFUSED) {
1324a285bdaSBarry Smith         refcnt++;
1334a285bdaSBarry Smith         if (refcnt > 5) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SYS,"Connection refused by remote host %s port %d",hostname,portnum);
134955c1f14SBarry Smith         ierr = PetscInfo(0,"Connection refused in attaching socket, trying again\n");CHKERRQ(ierr);
1355c6c1daeSBarry Smith         sleep((unsigned) 1);
1365c6c1daeSBarry Smith       } else {
1375c6c1daeSBarry Smith         perror(NULL); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error");
1385c6c1daeSBarry Smith       }
1395c6c1daeSBarry Smith #endif
1405c6c1daeSBarry Smith       flg = PETSC_TRUE;
1415c6c1daeSBarry Smith #if defined(PETSC_HAVE_CLOSESOCKET)
1425c6c1daeSBarry Smith       closesocket(s);
1435c6c1daeSBarry Smith #else
1445c6c1daeSBarry Smith       close(s);
1455c6c1daeSBarry Smith #endif
146a297a907SKarl Rupp     } else flg = PETSC_FALSE;
1475c6c1daeSBarry Smith   }
1485c6c1daeSBarry Smith   *t = s;
1495c6c1daeSBarry Smith   PetscFunctionReturn(0);
1505c6c1daeSBarry Smith }
1515c6c1daeSBarry Smith 
1525c6c1daeSBarry Smith #define MAXHOSTNAME 100
1535c6c1daeSBarry Smith #undef __FUNCT__
1545c6c1daeSBarry Smith #define __FUNCT__ "PetscSocketEstablish"
1555c6c1daeSBarry Smith /*
1565c6c1daeSBarry Smith    PetscSocketEstablish - starts a listener on a socket
1575c6c1daeSBarry Smith 
1585c6c1daeSBarry Smith .seealso:   PetscSocketListen()
1595c6c1daeSBarry Smith */
1605847ff97SBarry Smith PETSC_INTERN PetscErrorCode PetscSocketEstablish(int portnum,int *ss)
1615c6c1daeSBarry Smith {
1625c6c1daeSBarry Smith   char               myname[MAXHOSTNAME+1];
1635c6c1daeSBarry Smith   int                s;
1645c6c1daeSBarry Smith   PetscErrorCode     ierr;
1655c6c1daeSBarry Smith   struct sockaddr_in sa;
1665c6c1daeSBarry Smith   struct hostent     *hp;
1675c6c1daeSBarry Smith 
1685c6c1daeSBarry Smith   PetscFunctionBegin;
1695c6c1daeSBarry Smith   ierr = PetscGetHostName(myname,MAXHOSTNAME);CHKERRQ(ierr);
1705c6c1daeSBarry Smith 
1715c6c1daeSBarry Smith   ierr = PetscMemzero(&sa,sizeof(struct sockaddr_in));CHKERRQ(ierr);
1725c6c1daeSBarry Smith 
1735c6c1daeSBarry Smith   hp = gethostbyname(myname);
1745c6c1daeSBarry Smith   if (!hp) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Unable to get hostent information from system");
1755c6c1daeSBarry Smith 
1765c6c1daeSBarry Smith   sa.sin_family = hp->h_addrtype;
1775c6c1daeSBarry Smith   sa.sin_port   = htons((u_short)portnum);
1785c6c1daeSBarry Smith 
1795c6c1daeSBarry Smith   if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error running socket() command");
1805c6c1daeSBarry Smith #if defined(PETSC_HAVE_SO_REUSEADDR)
1815c6c1daeSBarry Smith   {
1825c6c1daeSBarry Smith     int optval = 1; /* Turn on the option */
1835c6c1daeSBarry Smith     ierr = setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&optval,sizeof(optval));CHKERRQ(ierr);
1845c6c1daeSBarry Smith   }
1855c6c1daeSBarry Smith #endif
1865c6c1daeSBarry Smith 
1875c6c1daeSBarry Smith   while (bind(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
1885c6c1daeSBarry Smith #if defined(PETSC_HAVE_WSAGETLASTERROR)
1895c6c1daeSBarry Smith     ierr = WSAGetLastError();
1905c6c1daeSBarry Smith     if (ierr != WSAEADDRINUSE) {
1915c6c1daeSBarry Smith #else
1925c6c1daeSBarry Smith     if (errno != EADDRINUSE) {
1935c6c1daeSBarry Smith #endif
1945c6c1daeSBarry Smith       close(s);
1955c6c1daeSBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error from bind()");
1965c6c1daeSBarry Smith     }
1975c6c1daeSBarry Smith   }
1985c6c1daeSBarry Smith   listen(s,0);
1995c6c1daeSBarry Smith   *ss = s;
2005c6c1daeSBarry Smith   return(0);
2015c6c1daeSBarry Smith }
2025c6c1daeSBarry Smith 
2035c6c1daeSBarry Smith #undef __FUNCT__
2045c6c1daeSBarry Smith #define __FUNCT__ "PetscSocketListen"
2055c6c1daeSBarry Smith /*
2065c6c1daeSBarry Smith    PetscSocketListens - Listens at a socket created with PetscSocketEstablish()
2075c6c1daeSBarry Smith 
2085c6c1daeSBarry Smith .seealso:   PetscSocketEstablish()
2095c6c1daeSBarry Smith */
2105847ff97SBarry Smith PETSC_INTERN PetscErrorCode PetscSocketListen(int listenport,int *t)
2115c6c1daeSBarry Smith {
2125c6c1daeSBarry Smith   struct sockaddr_in isa;
2135c6c1daeSBarry Smith #if defined(PETSC_HAVE_ACCEPT_SIZE_T)
2145c6c1daeSBarry Smith   size_t             i;
2155c6c1daeSBarry Smith #else
2165c6c1daeSBarry Smith   int                i;
2175c6c1daeSBarry Smith #endif
2185c6c1daeSBarry Smith 
2195c6c1daeSBarry Smith   PetscFunctionBegin;
2205c6c1daeSBarry Smith   /* wait for someone to try to connect */
2215c6c1daeSBarry Smith   i = sizeof(struct sockaddr_in);
2225c6c1daeSBarry Smith   if ((*t = accept(listenport,(struct sockaddr*)&isa,(socklen_t*)&i)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"error from accept()\n");
2235c6c1daeSBarry Smith   PetscFunctionReturn(0);
2245c6c1daeSBarry Smith }
2255c6c1daeSBarry Smith 
2265c6c1daeSBarry Smith #undef __FUNCT__
2275c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerSocketOpen"
2285c6c1daeSBarry Smith /*@C
2295c6c1daeSBarry Smith    PetscViewerSocketOpen - Opens a connection to a MATLAB or other socket
2305c6c1daeSBarry Smith         based server.
2315c6c1daeSBarry Smith 
2325c6c1daeSBarry Smith    Collective on MPI_Comm
2335c6c1daeSBarry Smith 
2345c6c1daeSBarry Smith    Input Parameters:
2355c6c1daeSBarry Smith +  comm - the MPI communicator
2360298fd71SBarry Smith .  machine - the machine the server is running on,, use NULL for the local machine, use "server" to passively wait for
2375c6c1daeSBarry Smith              a connection from elsewhere
2385c6c1daeSBarry Smith -  port - the port to connect to, use PETSC_DEFAULT for the default
2395c6c1daeSBarry Smith 
2405c6c1daeSBarry Smith    Output Parameter:
2415c6c1daeSBarry Smith .  lab - a context to use when communicating with the server
2425c6c1daeSBarry Smith 
2435c6c1daeSBarry Smith    Level: intermediate
2445c6c1daeSBarry Smith 
2455c6c1daeSBarry Smith    Notes:
2465c6c1daeSBarry Smith    Most users should employ the following commands to access the
2475c6c1daeSBarry Smith    MATLAB PetscViewers
2485c6c1daeSBarry Smith $
2495c6c1daeSBarry Smith $    PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer)
2505c6c1daeSBarry Smith $    MatView(Mat matrix,PetscViewer viewer)
2515c6c1daeSBarry Smith $
2525c6c1daeSBarry Smith $                or
2535c6c1daeSBarry Smith $
2545c6c1daeSBarry Smith $    PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer)
2555c6c1daeSBarry Smith $    VecView(Vec vector,PetscViewer viewer)
2565c6c1daeSBarry Smith 
2575c6c1daeSBarry Smith    Options Database Keys:
2585c6c1daeSBarry Smith    For use with  PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF,
2595c6c1daeSBarry Smith    PETSC_VIEWER_SOCKET_() or if
2600298fd71SBarry Smith     NULL is passed for machine or PETSC_DEFAULT is passed for port
2615c6c1daeSBarry Smith $    -viewer_socket_machine <machine>
2625c6c1daeSBarry Smith $    -viewer_socket_port <port>
2635c6c1daeSBarry Smith 
2645c6c1daeSBarry Smith    Environmental variables:
2655c6c1daeSBarry Smith +   PETSC_VIEWER_SOCKET_PORT portnumber
2665c6c1daeSBarry Smith -   PETSC_VIEWER_SOCKET_MACHINE machine name
2675c6c1daeSBarry Smith 
2685c6c1daeSBarry Smith      Currently the only socket client available is MATLAB. See
2695c6c1daeSBarry Smith      src/dm/da/examples/tests/ex12.c and ex12.m for an example of usage.
2705c6c1daeSBarry Smith 
2715c6c1daeSBarry Smith    Notes: The socket viewer is in some sense a subclass of the binary viewer, to read and write to the socket
2725c6c1daeSBarry Smith           use PetscViewerBinaryRead/Write/GetDescriptor().
2735c6c1daeSBarry Smith 
2745c6c1daeSBarry Smith    Concepts: MATLAB^sending data
2755c6c1daeSBarry Smith    Concepts: sockets^sending data
2765c6c1daeSBarry Smith 
2775c6c1daeSBarry Smith .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerSetType(),
2785c6c1daeSBarry Smith           PetscViewerSocketSetConnection(), PETSC_VIEWER_SOCKET_, PETSC_VIEWER_SOCKET_WORLD,
2795c6c1daeSBarry Smith           PETSC_VIEWER_SOCKET_SELF, PetscViewerBinaryWrite(), PetscViewerBinaryRead(), PetscViewerBinaryWriteStringArray(),
2805c6c1daeSBarry Smith           PetscBinaryViewerGetDescriptor()
2815c6c1daeSBarry Smith @*/
2825c6c1daeSBarry Smith PetscErrorCode  PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
2835c6c1daeSBarry Smith {
2845c6c1daeSBarry Smith   PetscErrorCode ierr;
2855c6c1daeSBarry Smith 
2865c6c1daeSBarry Smith   PetscFunctionBegin;
2875c6c1daeSBarry Smith   ierr = PetscViewerCreate(comm,lab);CHKERRQ(ierr);
2885c6c1daeSBarry Smith   ierr = PetscViewerSetType(*lab,PETSCVIEWERSOCKET);CHKERRQ(ierr);
2895c6c1daeSBarry Smith   ierr = PetscViewerSocketSetConnection(*lab,machine,port);CHKERRQ(ierr);
2905c6c1daeSBarry Smith   PetscFunctionReturn(0);
2915c6c1daeSBarry Smith }
2925c6c1daeSBarry Smith 
2935c6c1daeSBarry Smith #undef __FUNCT__
2945c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerSetFromOptions_Socket"
2954416b707SBarry Smith static PetscErrorCode PetscViewerSetFromOptions_Socket(PetscOptionItems *PetscOptionsObject,PetscViewer v)
2965c6c1daeSBarry Smith {
2975c6c1daeSBarry Smith   PetscErrorCode ierr;
2985c6c1daeSBarry Smith   PetscInt       def = -1;
2995c6c1daeSBarry Smith   char           sdef[256];
3005c6c1daeSBarry Smith   PetscBool      tflg;
3015c6c1daeSBarry Smith 
3025c6c1daeSBarry Smith   PetscFunctionBegin;
3035c6c1daeSBarry Smith   /*
3045c6c1daeSBarry Smith        These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they
3055c6c1daeSBarry Smith     are listed here for the GUI to display
3065c6c1daeSBarry Smith   */
307e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"Socket PetscViewer Options");CHKERRQ(ierr);
308ce94432eSBarry Smith   ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",sdef,16,&tflg);CHKERRQ(ierr);
3095c6c1daeSBarry Smith   if (tflg) {
3105c6c1daeSBarry Smith     ierr = PetscOptionsStringToInt(sdef,&def);CHKERRQ(ierr);
311a297a907SKarl Rupp   } else def = PETSCSOCKETDEFAULTPORT;
3125c6c1daeSBarry Smith   ierr = PetscOptionsInt("-viewer_socket_port","Port number to use for socket","PetscViewerSocketSetConnection",def,0,0);CHKERRQ(ierr);
3135c6c1daeSBarry Smith 
3145c6c1daeSBarry Smith   ierr = PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,0,0,0);CHKERRQ(ierr);
315ce94432eSBarry Smith   ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",sdef,256,&tflg);CHKERRQ(ierr);
3165c6c1daeSBarry Smith   if (!tflg) {
3175c6c1daeSBarry Smith     ierr = PetscGetHostName(sdef,256);CHKERRQ(ierr);
3185c6c1daeSBarry Smith   }
3195c6c1daeSBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
3205c6c1daeSBarry Smith   PetscFunctionReturn(0);
3215c6c1daeSBarry Smith }
3225c6c1daeSBarry Smith 
323*8556b5ebSBarry Smith /*MC
324*8556b5ebSBarry Smith    PETSCVIEWERSOCKET - A viewer that writes to a Unix socket
325*8556b5ebSBarry Smith 
326*8556b5ebSBarry Smith 
327*8556b5ebSBarry Smith .seealso:  PetscViewerSocketOpen(), PetscViewerDrawOpen(), PETSC_VIEWER_DRAW_(),PETSC_VIEWER_DRAW_SELF, PETSC_VIEWER_DRAW_WORLD,
328*8556b5ebSBarry Smith            PetscViewerCreate(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PETSCVIEWERBINARY, PETSCVIEWERDRAW,
329*8556b5ebSBarry Smith            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB,
330*8556b5ebSBarry Smith            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType()
331*8556b5ebSBarry Smith 
332*8556b5ebSBarry Smith M*/
333*8556b5ebSBarry Smith 
3345c6c1daeSBarry Smith #undef __FUNCT__
3355c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerCreate_Socket"
3368cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PetscViewerCreate_Socket(PetscViewer v)
3375c6c1daeSBarry Smith {
3385c6c1daeSBarry Smith   PetscViewer_Socket *vmatlab;
3395c6c1daeSBarry Smith   PetscErrorCode     ierr;
3405c6c1daeSBarry Smith 
3415c6c1daeSBarry Smith   PetscFunctionBegin;
342b00a9115SJed Brown   ierr                   = PetscNewLog(v,&vmatlab);CHKERRQ(ierr);
3435c6c1daeSBarry Smith   vmatlab->port          = 0;
3445c6c1daeSBarry Smith   v->data                = (void*)vmatlab;
3455c6c1daeSBarry Smith   v->ops->destroy        = PetscViewerDestroy_Socket;
3465c6c1daeSBarry Smith   v->ops->flush          = 0;
3475c6c1daeSBarry Smith   v->ops->setfromoptions = PetscViewerSetFromOptions_Socket;
3485c6c1daeSBarry Smith 
3495c6c1daeSBarry Smith   /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */
3505c6c1daeSBarry Smith   ierr                   = PetscObjectChangeTypeName((PetscObject)v,PETSCVIEWERBINARY);CHKERRQ(ierr);
3515c6c1daeSBarry Smith   PetscFunctionReturn(0);
3525c6c1daeSBarry Smith }
3535c6c1daeSBarry Smith 
3545c6c1daeSBarry Smith #undef __FUNCT__
3555c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerSocketSetConnection"
3565c6c1daeSBarry Smith /*@C
3575c6c1daeSBarry Smith       PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket
3585c6c1daeSBarry Smith              viewer is to use
3595c6c1daeSBarry Smith 
3605c6c1daeSBarry Smith   Logically Collective on PetscViewer
3615c6c1daeSBarry Smith 
3625c6c1daeSBarry Smith   Input Parameters:
3635c6c1daeSBarry Smith +   v - viewer to connect
3640298fd71SBarry Smith .   machine - host to connect to, use NULL for the local machine,use "server" to passively wait for
3655c6c1daeSBarry Smith              a connection from elsewhere
3665c6c1daeSBarry Smith -   port - the port on the machine one is connecting to, use PETSC_DEFAULT for default
3675c6c1daeSBarry Smith 
3685c6c1daeSBarry Smith     Level: advanced
3695c6c1daeSBarry Smith 
3705c6c1daeSBarry Smith .seealso: PetscViewerSocketOpen()
3715c6c1daeSBarry Smith @*/
3725c6c1daeSBarry Smith PetscErrorCode  PetscViewerSocketSetConnection(PetscViewer v,const char machine[],int port)
3735c6c1daeSBarry Smith {
3745c6c1daeSBarry Smith   PetscErrorCode     ierr;
3755c6c1daeSBarry Smith   PetscMPIInt        rank;
3765c6c1daeSBarry Smith   char               mach[256];
3775c6c1daeSBarry Smith   PetscBool          tflg;
3785c6c1daeSBarry Smith   PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)v->data;
3795c6c1daeSBarry Smith 
3805c6c1daeSBarry Smith   PetscFunctionBegin;
3815c6c1daeSBarry Smith   /* PetscValidLogicalCollectiveInt(v,port,3); not a PetscInt */
3825c6c1daeSBarry Smith   if (port <= 0) {
3835c6c1daeSBarry Smith     char portn[16];
384ce94432eSBarry Smith     ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",portn,16,&tflg);CHKERRQ(ierr);
3855c6c1daeSBarry Smith     if (tflg) {
3865c6c1daeSBarry Smith       PetscInt pport;
3875c6c1daeSBarry Smith       ierr = PetscOptionsStringToInt(portn,&pport);CHKERRQ(ierr);
3885c6c1daeSBarry Smith       port = (int)pport;
389a297a907SKarl Rupp     } else port = PETSCSOCKETDEFAULTPORT;
3905c6c1daeSBarry Smith   }
3915c6c1daeSBarry Smith   if (!machine) {
392ce94432eSBarry Smith     ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",mach,256,&tflg);CHKERRQ(ierr);
3935c6c1daeSBarry Smith     if (!tflg) {
3945c6c1daeSBarry Smith       ierr = PetscGetHostName(mach,256);CHKERRQ(ierr);
3955c6c1daeSBarry Smith     }
3965c6c1daeSBarry Smith   } else {
3975c6c1daeSBarry Smith     ierr = PetscStrncpy(mach,machine,256);CHKERRQ(ierr);
3985c6c1daeSBarry Smith   }
3995c6c1daeSBarry Smith 
400ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)v),&rank);CHKERRQ(ierr);
4015c6c1daeSBarry Smith   if (!rank) {
4025c6c1daeSBarry Smith     ierr = PetscStrcmp(mach,"server",&tflg);CHKERRQ(ierr);
4035c6c1daeSBarry Smith     if (tflg) {
4045c6c1daeSBarry Smith       int listenport;
4055c6c1daeSBarry Smith       ierr = PetscInfo1(v,"Waiting for connection from socket process on port %D\n",port);CHKERRQ(ierr);
4065c6c1daeSBarry Smith       ierr = PetscSocketEstablish(port,&listenport);CHKERRQ(ierr);
4075c6c1daeSBarry Smith       ierr = PetscSocketListen(listenport,&vmatlab->port);CHKERRQ(ierr);
4085c6c1daeSBarry Smith       close(listenport);
4095c6c1daeSBarry Smith     } else {
4105c6c1daeSBarry Smith       ierr = PetscInfo2(v,"Connecting to socket process on port %D machine %s\n",port,mach);CHKERRQ(ierr);
4115c6c1daeSBarry Smith       ierr = PetscOpenSocket(mach,port,&vmatlab->port);CHKERRQ(ierr);
4125c6c1daeSBarry Smith     }
4135c6c1daeSBarry Smith   }
4145c6c1daeSBarry Smith   PetscFunctionReturn(0);
4155c6c1daeSBarry Smith }
4165c6c1daeSBarry Smith 
4175c6c1daeSBarry Smith /* ---------------------------------------------------------------------*/
4185c6c1daeSBarry Smith /*
4195c6c1daeSBarry Smith     The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that
4205c6c1daeSBarry Smith   is attached to a communicator, in this case the attribute is a PetscViewer.
4215c6c1daeSBarry Smith */
4225c6c1daeSBarry Smith static PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID;
4235c6c1daeSBarry Smith 
4245c6c1daeSBarry Smith 
4255c6c1daeSBarry Smith #undef __FUNCT__
4265c6c1daeSBarry Smith #define __FUNCT__ "PETSC_VIEWER_SOCKET_"
4275c6c1daeSBarry Smith /*@C
4285c6c1daeSBarry Smith      PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator.
4295c6c1daeSBarry Smith 
4305c6c1daeSBarry Smith      Collective on MPI_Comm
4315c6c1daeSBarry Smith 
4325c6c1daeSBarry Smith      Input Parameter:
4335c6c1daeSBarry Smith .    comm - the MPI communicator to share the socket PetscViewer
4345c6c1daeSBarry Smith 
4355c6c1daeSBarry Smith      Level: intermediate
4365c6c1daeSBarry Smith 
4375c6c1daeSBarry Smith    Options Database Keys:
4385c6c1daeSBarry Smith    For use with the default PETSC_VIEWER_SOCKET_WORLD or if
4390298fd71SBarry Smith     NULL is passed for machine or PETSC_DEFAULT is passed for port
4405c6c1daeSBarry Smith $    -viewer_socket_machine <machine>
4415c6c1daeSBarry Smith $    -viewer_socket_port <port>
4425c6c1daeSBarry Smith 
4435c6c1daeSBarry Smith    Environmental variables:
4445c6c1daeSBarry Smith +   PETSC_VIEWER_SOCKET_PORT portnumber
4455c6c1daeSBarry Smith -   PETSC_VIEWER_SOCKET_MACHINE machine name
4465c6c1daeSBarry Smith 
4475c6c1daeSBarry Smith      Notes:
4485c6c1daeSBarry Smith      Unlike almost all other PETSc routines, PetscViewer_SOCKET_ does not return
4495c6c1daeSBarry Smith      an error code.  The socket PetscViewer is usually used in the form
4505c6c1daeSBarry Smith $       XXXView(XXX object,PETSC_VIEWER_SOCKET_(comm));
4515c6c1daeSBarry Smith 
4525c6c1daeSBarry Smith      Currently the only socket client available is MATLAB. See
4535c6c1daeSBarry Smith      src/dm/da/examples/tests/ex12.c and ex12.m for an example of usage.
4545c6c1daeSBarry Smith 
4555c6c1daeSBarry Smith      Connects to a waiting socket and stays connected until PetscViewerDestroy() is called.
4565c6c1daeSBarry Smith 
4575c6c1daeSBarry Smith      Use this for communicating with an interactive MATLAB session, see PETSC_VIEWER_MATLAB_() for communicating with the MATLAB engine.
4585c6c1daeSBarry Smith 
4595c6c1daeSBarry Smith .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(),
4605c6c1daeSBarry Smith           PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_(), PetscViewerBinaryWrite(), PetscViewerBinaryRead(),
4615c6c1daeSBarry Smith           PetscViewerBinaryWriteStringArray(), PetscBinaryViewerGetDescriptor(), PETSC_VIEWER_MATLAB_()
4625c6c1daeSBarry Smith @*/
4635c6c1daeSBarry Smith PetscViewer  PETSC_VIEWER_SOCKET_(MPI_Comm comm)
4645c6c1daeSBarry Smith {
4655c6c1daeSBarry Smith   PetscErrorCode ierr;
4665c6c1daeSBarry Smith   PetscBool      flg;
4675c6c1daeSBarry Smith   PetscViewer    viewer;
4685c6c1daeSBarry Smith   MPI_Comm       ncomm;
4695c6c1daeSBarry Smith 
4705c6c1daeSBarry Smith   PetscFunctionBegin;
471efca3c55SSatish Balay   ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
4725c6c1daeSBarry Smith   if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) {
4735c6c1daeSBarry Smith     ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Socket_keyval,0);
474efca3c55SSatish Balay     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
4755c6c1daeSBarry Smith   }
4765c6c1daeSBarry Smith   ierr = MPI_Attr_get(ncomm,Petsc_Viewer_Socket_keyval,(void**)&viewer,(int*)&flg);
477efca3c55SSatish Balay   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
4785c6c1daeSBarry Smith   if (!flg) { /* PetscViewer not yet created */
4795c6c1daeSBarry Smith     ierr = PetscViewerSocketOpen(ncomm,0,0,&viewer);
480efca3c55SSatish Balay     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
4815c6c1daeSBarry Smith     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
482efca3c55SSatish Balay     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
4835c6c1daeSBarry Smith     ierr = MPI_Attr_put(ncomm,Petsc_Viewer_Socket_keyval,(void*)viewer);
484efca3c55SSatish Balay     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
4855c6c1daeSBarry Smith   }
4865c6c1daeSBarry Smith   ierr = PetscCommDestroy(&ncomm);
487efca3c55SSatish Balay   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
4885c6c1daeSBarry Smith   PetscFunctionReturn(viewer);
4895c6c1daeSBarry Smith }
4905c6c1daeSBarry Smith 
491