xref: /petsc/src/sys/classes/viewer/impls/socket/send.c (revision a30fc760a10df938ba82184fb293564c6a2da375)
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
229*a30fc760SBarry Smith    PetscViewerSocketOpen - Opens a connection to a MATLAB or other socket based server.
2305c6c1daeSBarry Smith 
2315c6c1daeSBarry Smith    Collective on MPI_Comm
2325c6c1daeSBarry Smith 
2335c6c1daeSBarry Smith    Input Parameters:
2345c6c1daeSBarry Smith +  comm - the MPI communicator
2350298fd71SBarry Smith .  machine - the machine the server is running on,, use NULL for the local machine, use "server" to passively wait for
2365c6c1daeSBarry Smith              a connection from elsewhere
2375c6c1daeSBarry Smith -  port - the port to connect to, use PETSC_DEFAULT for the default
2385c6c1daeSBarry Smith 
2395c6c1daeSBarry Smith    Output Parameter:
2405c6c1daeSBarry Smith .  lab - a context to use when communicating with the server
2415c6c1daeSBarry Smith 
2425c6c1daeSBarry Smith    Level: intermediate
2435c6c1daeSBarry Smith 
2445c6c1daeSBarry Smith    Notes:
2455c6c1daeSBarry Smith    Most users should employ the following commands to access the
2465c6c1daeSBarry Smith    MATLAB PetscViewers
2475c6c1daeSBarry Smith $
2485c6c1daeSBarry Smith $    PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer)
2495c6c1daeSBarry Smith $    MatView(Mat matrix,PetscViewer viewer)
2505c6c1daeSBarry Smith $
2515c6c1daeSBarry Smith $                or
2525c6c1daeSBarry Smith $
2535c6c1daeSBarry Smith $    PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer)
2545c6c1daeSBarry Smith $    VecView(Vec vector,PetscViewer viewer)
2555c6c1daeSBarry Smith 
2565c6c1daeSBarry Smith    Options Database Keys:
2575c6c1daeSBarry Smith    For use with  PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF,
2585c6c1daeSBarry Smith    PETSC_VIEWER_SOCKET_() or if
2590298fd71SBarry Smith     NULL is passed for machine or PETSC_DEFAULT is passed for port
2605c6c1daeSBarry Smith $    -viewer_socket_machine <machine>
2615c6c1daeSBarry Smith $    -viewer_socket_port <port>
2625c6c1daeSBarry Smith 
2635c6c1daeSBarry Smith    Environmental variables:
2645c6c1daeSBarry Smith +   PETSC_VIEWER_SOCKET_PORT portnumber
2655c6c1daeSBarry Smith -   PETSC_VIEWER_SOCKET_MACHINE machine name
2665c6c1daeSBarry Smith 
2675c6c1daeSBarry Smith      Currently the only socket client available is MATLAB. See
268*a30fc760SBarry Smith      src/dm/examples/tests/ex12.c and ex12.m for an example of usage.
2695c6c1daeSBarry Smith 
2705c6c1daeSBarry Smith    Notes: The socket viewer is in some sense a subclass of the binary viewer, to read and write to the socket
271*a30fc760SBarry Smith           use PetscViewerBinaryRead(), PetscViewerBinaryWrite(), PetscViewerBinarWriteStringArray(), PetscViewerBinaryGetDescriptor().
272*a30fc760SBarry Smith 
273*a30fc760SBarry Smith      Use this for communicating with an interactive MATLAB session, see PETSC_VIEWER_MATLAB_() for writing output to a
274*a30fc760SBarry Smith      .mat file. Use PetscMatlabEngineCreate() or PETSC_MATLAB_ENGINE_(), PETSC_MATLAB_ENGINE_SELF, or PETSC_MATLAB_ENGINE_WORLD
275*a30fc760SBarry Smith      for communicating with a MATLAB Engine
2765c6c1daeSBarry Smith 
2775c6c1daeSBarry Smith    Concepts: MATLAB^sending data
2785c6c1daeSBarry Smith    Concepts: sockets^sending data
2795c6c1daeSBarry Smith 
2805c6c1daeSBarry Smith .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerSetType(),
2815c6c1daeSBarry Smith           PetscViewerSocketSetConnection(), PETSC_VIEWER_SOCKET_, PETSC_VIEWER_SOCKET_WORLD,
2825c6c1daeSBarry Smith           PETSC_VIEWER_SOCKET_SELF, PetscViewerBinaryWrite(), PetscViewerBinaryRead(), PetscViewerBinaryWriteStringArray(),
283*a30fc760SBarry Smith           PetscBinaryViewerGetDescriptor(), PetscMatlabEngineCreate()
2845c6c1daeSBarry Smith @*/
2855c6c1daeSBarry Smith PetscErrorCode  PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
2865c6c1daeSBarry Smith {
2875c6c1daeSBarry Smith   PetscErrorCode ierr;
2885c6c1daeSBarry Smith 
2895c6c1daeSBarry Smith   PetscFunctionBegin;
2905c6c1daeSBarry Smith   ierr = PetscViewerCreate(comm,lab);CHKERRQ(ierr);
2915c6c1daeSBarry Smith   ierr = PetscViewerSetType(*lab,PETSCVIEWERSOCKET);CHKERRQ(ierr);
2925c6c1daeSBarry Smith   ierr = PetscViewerSocketSetConnection(*lab,machine,port);CHKERRQ(ierr);
2935c6c1daeSBarry Smith   PetscFunctionReturn(0);
2945c6c1daeSBarry Smith }
2955c6c1daeSBarry Smith 
2965c6c1daeSBarry Smith #undef __FUNCT__
2975c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerSetFromOptions_Socket"
2984416b707SBarry Smith static PetscErrorCode PetscViewerSetFromOptions_Socket(PetscOptionItems *PetscOptionsObject,PetscViewer v)
2995c6c1daeSBarry Smith {
3005c6c1daeSBarry Smith   PetscErrorCode ierr;
3015c6c1daeSBarry Smith   PetscInt       def = -1;
3025c6c1daeSBarry Smith   char           sdef[256];
3035c6c1daeSBarry Smith   PetscBool      tflg;
3045c6c1daeSBarry Smith 
3055c6c1daeSBarry Smith   PetscFunctionBegin;
3065c6c1daeSBarry Smith   /*
3075c6c1daeSBarry Smith        These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they
3085c6c1daeSBarry Smith     are listed here for the GUI to display
3095c6c1daeSBarry Smith   */
310e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"Socket PetscViewer Options");CHKERRQ(ierr);
311ce94432eSBarry Smith   ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",sdef,16,&tflg);CHKERRQ(ierr);
3125c6c1daeSBarry Smith   if (tflg) {
3135c6c1daeSBarry Smith     ierr = PetscOptionsStringToInt(sdef,&def);CHKERRQ(ierr);
314a297a907SKarl Rupp   } else def = PETSCSOCKETDEFAULTPORT;
3155c6c1daeSBarry Smith   ierr = PetscOptionsInt("-viewer_socket_port","Port number to use for socket","PetscViewerSocketSetConnection",def,0,0);CHKERRQ(ierr);
3165c6c1daeSBarry Smith 
3175c6c1daeSBarry Smith   ierr = PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,0,0,0);CHKERRQ(ierr);
318ce94432eSBarry Smith   ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",sdef,256,&tflg);CHKERRQ(ierr);
3195c6c1daeSBarry Smith   if (!tflg) {
3205c6c1daeSBarry Smith     ierr = PetscGetHostName(sdef,256);CHKERRQ(ierr);
3215c6c1daeSBarry Smith   }
3225c6c1daeSBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
3235c6c1daeSBarry Smith   PetscFunctionReturn(0);
3245c6c1daeSBarry Smith }
3255c6c1daeSBarry Smith 
3265c6c1daeSBarry Smith #undef __FUNCT__
3275c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerCreate_Socket"
3288cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PetscViewerCreate_Socket(PetscViewer v)
3295c6c1daeSBarry Smith {
3305c6c1daeSBarry Smith   PetscViewer_Socket *vmatlab;
3315c6c1daeSBarry Smith   PetscErrorCode     ierr;
3325c6c1daeSBarry Smith 
3335c6c1daeSBarry Smith   PetscFunctionBegin;
334b00a9115SJed Brown   ierr                   = PetscNewLog(v,&vmatlab);CHKERRQ(ierr);
3355c6c1daeSBarry Smith   vmatlab->port          = 0;
3365c6c1daeSBarry Smith   v->data                = (void*)vmatlab;
3375c6c1daeSBarry Smith   v->ops->destroy        = PetscViewerDestroy_Socket;
3385c6c1daeSBarry Smith   v->ops->flush          = 0;
3395c6c1daeSBarry Smith   v->ops->setfromoptions = PetscViewerSetFromOptions_Socket;
3405c6c1daeSBarry Smith 
3415c6c1daeSBarry Smith   /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */
3425c6c1daeSBarry Smith   ierr                   = PetscObjectChangeTypeName((PetscObject)v,PETSCVIEWERBINARY);CHKERRQ(ierr);
3435c6c1daeSBarry Smith   PetscFunctionReturn(0);
3445c6c1daeSBarry Smith }
3455c6c1daeSBarry Smith 
3465c6c1daeSBarry Smith #undef __FUNCT__
3475c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerSocketSetConnection"
3485c6c1daeSBarry Smith /*@C
3495c6c1daeSBarry Smith       PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket
3505c6c1daeSBarry Smith              viewer is to use
3515c6c1daeSBarry Smith 
3525c6c1daeSBarry Smith   Logically Collective on PetscViewer
3535c6c1daeSBarry Smith 
3545c6c1daeSBarry Smith   Input Parameters:
3555c6c1daeSBarry Smith +   v - viewer to connect
3560298fd71SBarry Smith .   machine - host to connect to, use NULL for the local machine,use "server" to passively wait for
3575c6c1daeSBarry Smith              a connection from elsewhere
3585c6c1daeSBarry Smith -   port - the port on the machine one is connecting to, use PETSC_DEFAULT for default
3595c6c1daeSBarry Smith 
3605c6c1daeSBarry Smith     Level: advanced
3615c6c1daeSBarry Smith 
3625c6c1daeSBarry Smith .seealso: PetscViewerSocketOpen()
3635c6c1daeSBarry Smith @*/
3645c6c1daeSBarry Smith PetscErrorCode  PetscViewerSocketSetConnection(PetscViewer v,const char machine[],int port)
3655c6c1daeSBarry Smith {
3665c6c1daeSBarry Smith   PetscErrorCode     ierr;
3675c6c1daeSBarry Smith   PetscMPIInt        rank;
3685c6c1daeSBarry Smith   char               mach[256];
3695c6c1daeSBarry Smith   PetscBool          tflg;
3705c6c1daeSBarry Smith   PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)v->data;
3715c6c1daeSBarry Smith 
3725c6c1daeSBarry Smith   PetscFunctionBegin;
3735c6c1daeSBarry Smith   /* PetscValidLogicalCollectiveInt(v,port,3); not a PetscInt */
3745c6c1daeSBarry Smith   if (port <= 0) {
3755c6c1daeSBarry Smith     char portn[16];
376ce94432eSBarry Smith     ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",portn,16,&tflg);CHKERRQ(ierr);
3775c6c1daeSBarry Smith     if (tflg) {
3785c6c1daeSBarry Smith       PetscInt pport;
3795c6c1daeSBarry Smith       ierr = PetscOptionsStringToInt(portn,&pport);CHKERRQ(ierr);
3805c6c1daeSBarry Smith       port = (int)pport;
381a297a907SKarl Rupp     } else port = PETSCSOCKETDEFAULTPORT;
3825c6c1daeSBarry Smith   }
3835c6c1daeSBarry Smith   if (!machine) {
384ce94432eSBarry Smith     ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",mach,256,&tflg);CHKERRQ(ierr);
3855c6c1daeSBarry Smith     if (!tflg) {
3865c6c1daeSBarry Smith       ierr = PetscGetHostName(mach,256);CHKERRQ(ierr);
3875c6c1daeSBarry Smith     }
3885c6c1daeSBarry Smith   } else {
3895c6c1daeSBarry Smith     ierr = PetscStrncpy(mach,machine,256);CHKERRQ(ierr);
3905c6c1daeSBarry Smith   }
3915c6c1daeSBarry Smith 
392ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)v),&rank);CHKERRQ(ierr);
3935c6c1daeSBarry Smith   if (!rank) {
3945c6c1daeSBarry Smith     ierr = PetscStrcmp(mach,"server",&tflg);CHKERRQ(ierr);
3955c6c1daeSBarry Smith     if (tflg) {
3965c6c1daeSBarry Smith       int listenport;
3975c6c1daeSBarry Smith       ierr = PetscInfo1(v,"Waiting for connection from socket process on port %D\n",port);CHKERRQ(ierr);
3985c6c1daeSBarry Smith       ierr = PetscSocketEstablish(port,&listenport);CHKERRQ(ierr);
3995c6c1daeSBarry Smith       ierr = PetscSocketListen(listenport,&vmatlab->port);CHKERRQ(ierr);
4005c6c1daeSBarry Smith       close(listenport);
4015c6c1daeSBarry Smith     } else {
4025c6c1daeSBarry Smith       ierr = PetscInfo2(v,"Connecting to socket process on port %D machine %s\n",port,mach);CHKERRQ(ierr);
4035c6c1daeSBarry Smith       ierr = PetscOpenSocket(mach,port,&vmatlab->port);CHKERRQ(ierr);
4045c6c1daeSBarry Smith     }
4055c6c1daeSBarry Smith   }
4065c6c1daeSBarry Smith   PetscFunctionReturn(0);
4075c6c1daeSBarry Smith }
4085c6c1daeSBarry Smith 
4095c6c1daeSBarry Smith /* ---------------------------------------------------------------------*/
4105c6c1daeSBarry Smith /*
4115c6c1daeSBarry Smith     The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that
4125c6c1daeSBarry Smith   is attached to a communicator, in this case the attribute is a PetscViewer.
4135c6c1daeSBarry Smith */
4145c6c1daeSBarry Smith static PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID;
4155c6c1daeSBarry Smith 
4165c6c1daeSBarry Smith 
4175c6c1daeSBarry Smith #undef __FUNCT__
4185c6c1daeSBarry Smith #define __FUNCT__ "PETSC_VIEWER_SOCKET_"
4195c6c1daeSBarry Smith /*@C
4205c6c1daeSBarry Smith      PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator.
4215c6c1daeSBarry Smith 
4225c6c1daeSBarry Smith      Collective on MPI_Comm
4235c6c1daeSBarry Smith 
4245c6c1daeSBarry Smith      Input Parameter:
4255c6c1daeSBarry Smith .    comm - the MPI communicator to share the socket PetscViewer
4265c6c1daeSBarry Smith 
4275c6c1daeSBarry Smith      Level: intermediate
4285c6c1daeSBarry Smith 
4295c6c1daeSBarry Smith    Options Database Keys:
4305c6c1daeSBarry Smith    For use with the default PETSC_VIEWER_SOCKET_WORLD or if
4310298fd71SBarry Smith     NULL is passed for machine or PETSC_DEFAULT is passed for port
4325c6c1daeSBarry Smith $    -viewer_socket_machine <machine>
4335c6c1daeSBarry Smith $    -viewer_socket_port <port>
4345c6c1daeSBarry Smith 
4355c6c1daeSBarry Smith    Environmental variables:
4365c6c1daeSBarry Smith +   PETSC_VIEWER_SOCKET_PORT portnumber
4375c6c1daeSBarry Smith -   PETSC_VIEWER_SOCKET_MACHINE machine name
4385c6c1daeSBarry Smith 
4395c6c1daeSBarry Smith      Notes:
4405c6c1daeSBarry Smith      Unlike almost all other PETSc routines, PetscViewer_SOCKET_ does not return
4415c6c1daeSBarry Smith      an error code.  The socket PetscViewer is usually used in the form
4425c6c1daeSBarry Smith $       XXXView(XXX object,PETSC_VIEWER_SOCKET_(comm));
4435c6c1daeSBarry Smith 
4445c6c1daeSBarry Smith      Currently the only socket client available is MATLAB. See
445*a30fc760SBarry Smith      src/dm/examples/tests/ex12.c and ex12.m for an example of usage.
4465c6c1daeSBarry Smith 
4475c6c1daeSBarry Smith      Connects to a waiting socket and stays connected until PetscViewerDestroy() is called.
4485c6c1daeSBarry Smith 
449*a30fc760SBarry Smith      Use this for communicating with an interactive MATLAB session, see PETSC_VIEWER_MATLAB_() for writing output to a
450*a30fc760SBarry Smith      .mat file. Use PetscMatlabEngineCreate() or PETSC_MATLAB_ENGINE_(), PETSC_MATLAB_ENGINE_SELF, or PETSC_MATLAB_ENGINE_WORLD
451*a30fc760SBarry Smith      for communicating with a MATLAB Engine
4525c6c1daeSBarry Smith 
4535c6c1daeSBarry Smith .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(),
4545c6c1daeSBarry Smith           PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_(), PetscViewerBinaryWrite(), PetscViewerBinaryRead(),
455*a30fc760SBarry Smith           PetscViewerBinaryWriteStringArray(), PetscViewerBinaryGetDescriptor(), PETSC_VIEWER_MATLAB_()
4565c6c1daeSBarry Smith @*/
4575c6c1daeSBarry Smith PetscViewer  PETSC_VIEWER_SOCKET_(MPI_Comm comm)
4585c6c1daeSBarry Smith {
4595c6c1daeSBarry Smith   PetscErrorCode ierr;
4605c6c1daeSBarry Smith   PetscBool      flg;
4615c6c1daeSBarry Smith   PetscViewer    viewer;
4625c6c1daeSBarry Smith   MPI_Comm       ncomm;
4635c6c1daeSBarry Smith 
4645c6c1daeSBarry Smith   PetscFunctionBegin;
465efca3c55SSatish 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);}
4665c6c1daeSBarry Smith   if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) {
4675c6c1daeSBarry Smith     ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Socket_keyval,0);
468efca3c55SSatish Balay     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
4695c6c1daeSBarry Smith   }
4705c6c1daeSBarry Smith   ierr = MPI_Attr_get(ncomm,Petsc_Viewer_Socket_keyval,(void**)&viewer,(int*)&flg);
471efca3c55SSatish Balay   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
4725c6c1daeSBarry Smith   if (!flg) { /* PetscViewer not yet created */
4735c6c1daeSBarry Smith     ierr = PetscViewerSocketOpen(ncomm,0,0,&viewer);
474efca3c55SSatish Balay     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
4755c6c1daeSBarry Smith     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
476efca3c55SSatish Balay     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
4775c6c1daeSBarry Smith     ierr = MPI_Attr_put(ncomm,Petsc_Viewer_Socket_keyval,(void*)viewer);
478efca3c55SSatish Balay     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
4795c6c1daeSBarry Smith   }
4805c6c1daeSBarry Smith   ierr = PetscCommDestroy(&ncomm);
481efca3c55SSatish Balay   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
4825c6c1daeSBarry Smith   PetscFunctionReturn(viewer);
4835c6c1daeSBarry Smith }
4845c6c1daeSBarry Smith 
485