LCOV - code coverage report
Current view: top level - src - sockets.c (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:71c3ab0) Lines: 0.0 % 104 0
Test Date: 2026-07-25 06:35:44 Functions: 0.0 % 9 0

            Line data    Source code
       1              : /*----------------------------------------------------------------------------*/
       2              : /*  CP2K: A general program to perform molecular dynamics simulations         */
       3              : /*  Copyright 2000-2026 CP2K developers group <https://cp2k.org>              */
       4              : /*                                                                            */
       5              : /*  SPDX-License-Identifier: GPL-2.0-or-later                                 */
       6              : /*----------------------------------------------------------------------------*/
       7              : 
       8              : /*----------------------------------------------------------------------------*/
       9              : /*  Copyright (C) 2013, Joshua More and Michele Ceriotti                      */
      10              : /*                                                                            */
      11              : /*  Permission is hereby granted, free of charge, to any person obtaining     */
      12              : /*  a copy of this software and associated documentation files (the           */
      13              : /*  "Software"), to deal in the Software without restriction, including       */
      14              : /*  without limitation the rights to use, copy, modify, merge, publish,       */
      15              : /*  distribute, sublicense, and/or sell copies of the Software, and to        */
      16              : /*  permit persons to whom the Software is furnished to do so, subject to     */
      17              : /*  the following conditions:                                                 */
      18              : /*                                                                            */
      19              : /*  The above copyright notice and this permission notice shall be included   */
      20              : /*  in all copies or substantial portions of the Software.                    */
      21              : /*                                                                            */
      22              : /*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,           */
      23              : /*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF        */
      24              : /*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.    */
      25              : /*  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY      */
      26              : /*  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,      */
      27              : /*  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE         */
      28              : /*  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                    */
      29              : /*----------------------------------------------------------------------------*/
      30              : 
      31              : /*******************************************************************************
      32              :  * \brief A minimal wrapper for socket communication.
      33              :  *        Contains both the functions that transmit data to the socket and read
      34              :  *        the data back out again once finished, and the function which opens
      35              :  *        the socket initially. Can be linked to a FORTRAN code that does not
      36              :  *        support sockets natively.
      37              :  * \author Joshua More and Michele Ceriotti
      38              :  ******************************************************************************/
      39              : #ifndef __NO_SOCKETS
      40              : 
      41              : #define _POSIX_C_SOURCE 200809L
      42              : 
      43              : #include <math.h>
      44              : #include <netdb.h>
      45              : #include <netinet/in.h>
      46              : #include <stdio.h>
      47              : #include <stdlib.h>
      48              : #include <string.h>
      49              : #include <sys/select.h>
      50              : #include <sys/socket.h>
      51              : #include <sys/types.h>
      52              : #include <sys/un.h>
      53              : #include <time.h>
      54              : #include <unistd.h>
      55              : 
      56              : /*******************************************************************************
      57              :  * \brief Opens and connects a socket.
      58              :  * \param psockfd The id of the socket that will be created.
      59              :  * \param inet    An integer that determines whether the socket will be an inet
      60              :  *                or unix domain socket. Gives unix if 0, inet otherwise.
      61              :  * \param port    The port number for the socket to be created. Low numbers are
      62              :  *                often reserved for important channels, so use of numbers of 4
      63              :  *                or more digits is recommended.
      64              :  * \param host    The name of the host server (inet socket), or the full path
      65              :  *                of the UNIX socket file (unix socket). The caller is
      66              :  *                responsible for building this path, e.g. by prepending a
      67              :  *                prefix such as "/tmp/ipi_".
      68              :  * \note  Fortran passes an extra argument for the string length, but this is
      69              :  *        ignored here for C compatibility.
      70              :  ******************************************************************************/
      71            0 : void open_connect_socket(int *psockfd, int *inet, int *port, char *host) {
      72            0 :   int sockfd, ai_err;
      73              : 
      74            0 :   if (*inet > 0) { // creates an internet socket
      75              : 
      76              :     // fetches information on the host
      77            0 :     struct addrinfo hints, *res;
      78            0 :     char service[256];
      79              : 
      80            0 :     memset(&hints, 0, sizeof(hints));
      81            0 :     hints.ai_socktype = SOCK_STREAM;
      82            0 :     hints.ai_family = AF_INET;
      83            0 :     hints.ai_flags = AI_PASSIVE;
      84              : 
      85            0 :     sprintf(service, "%d", *port); // convert the port number to a string
      86            0 :     ai_err = getaddrinfo(host, service, &hints, &res);
      87            0 :     if (ai_err != 0) {
      88            0 :       perror("Error fetching host data. Wrong host name?");
      89            0 :       exit(-1);
      90              :     }
      91              : 
      92              :     // creates socket
      93            0 :     sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
      94            0 :     if (sockfd < 0) {
      95            0 :       perror("Error opening socket");
      96            0 :       exit(-1);
      97              :     }
      98              : 
      99              :     // makes connection
     100            0 :     if (connect(sockfd, res->ai_addr, res->ai_addrlen) < 0) {
     101            0 :       perror("Error opening INET socket: wrong port or server unreachable");
     102            0 :       exit(-1);
     103              :     }
     104            0 :     freeaddrinfo(res);
     105              :   } else { // creates a unix socket
     106            0 :     struct sockaddr_un serv_addr;
     107              : 
     108              :     // fills up details of the socket address
     109            0 :     memset(&serv_addr, 0, sizeof(serv_addr));
     110            0 :     serv_addr.sun_family = AF_UNIX;
     111            0 :     strcpy(serv_addr.sun_path, host);
     112              : 
     113              :     // creates the socket
     114            0 :     sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
     115              : 
     116              :     // connects
     117            0 :     if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
     118            0 :       perror(
     119              :           "Error opening UNIX socket: path unavailable, or already existing");
     120            0 :       exit(-1);
     121              :     }
     122              :   }
     123              : 
     124            0 :   *psockfd = sockfd;
     125            0 : }
     126              : 
     127              : /*******************************************************************************
     128              :  * \brief Opens and binds a socket.
     129              :  * \param psockfd The id of the socket that will be created.
     130              :  * \param inet    An integer that determines whether the socket will be an inet
     131              :  *                or unix domain socket. Gives unix if 0, inet otherwise.
     132              :  * \param port    The port number for the socket to be created. Low numbers are
     133              :  *                often reserved for important channels, so use of numbers of 4
     134              :  *                or more digits is recommended.
     135              :  * \param host    The name of the host server.
     136              :  * \note  Fortran passes an extra argument for the string length, but this is
     137              :  *        ignored here for C compatibility.
     138              :  ******************************************************************************/
     139            0 : void open_bind_socket(int *psockfd, int *inet, int *port, char *host) {
     140            0 :   int sockfd, ai_err;
     141              : 
     142            0 :   if (*inet > 0) { // creates an internet socket
     143              : 
     144              :     // fetches information on the host
     145            0 :     struct addrinfo hints, *res;
     146            0 :     char service[256];
     147              : 
     148            0 :     memset(&hints, 0, sizeof(hints));
     149            0 :     hints.ai_socktype = SOCK_STREAM;
     150            0 :     hints.ai_family = AF_INET;
     151            0 :     hints.ai_flags = AI_PASSIVE;
     152              : 
     153            0 :     sprintf(service, "%d", *port); // convert the port number to a string
     154            0 :     ai_err = getaddrinfo(host, service, &hints, &res);
     155            0 :     if (ai_err != 0) {
     156            0 :       perror("Error fetching host data. Wrong host name?");
     157            0 :       exit(-1);
     158              :     }
     159              : 
     160              :     // creates socket
     161            0 :     sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
     162            0 :     if (sockfd < 0) {
     163            0 :       perror("Error opening socket");
     164            0 :       exit(-1);
     165              :     }
     166              : 
     167              :     // binds
     168            0 :     if (bind(sockfd, res->ai_addr, res->ai_addrlen) < 0) {
     169            0 :       perror("Error binding INET socket: wrong port or server unreachable");
     170            0 :       exit(-1);
     171              :     }
     172            0 :     freeaddrinfo(res);
     173              :   } else { // creates a unix socket
     174            0 :     struct sockaddr_un serv_addr;
     175              : 
     176              :     // fills up details of the socket address
     177            0 :     memset(&serv_addr, 0, sizeof(serv_addr));
     178            0 :     serv_addr.sun_family = AF_UNIX;
     179            0 :     strcpy(serv_addr.sun_path, host);
     180              : 
     181              :     // creates the socket
     182            0 :     sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
     183              : 
     184            0 :     remove(serv_addr.sun_path);
     185              : 
     186              :     // binds
     187            0 :     if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
     188            0 :       perror(
     189              :           "Error binding UNIX socket: path unavailable, or already existing");
     190            0 :       exit(-1);
     191              :     }
     192              :   }
     193              : 
     194            0 :   *psockfd = sockfd;
     195            0 : }
     196              : 
     197              : /*******************************************************************************
     198              :  * \brief Writes to a socket.
     199              :  * \param psockfd The id of the socket that will be written to.
     200              :  * \param data    The data to be written to the socket.
     201              :  * \param plen    The length of the data in bytes.
     202              :  ******************************************************************************/
     203            0 : void writebuffer(int *psockfd, char *data, int *plen) {
     204            0 :   int n;
     205            0 :   int sockfd = *psockfd;
     206            0 :   int len = *plen;
     207              : 
     208            0 :   n = write(sockfd, data, len);
     209            0 :   if (n < 0) {
     210            0 :     perror("Error writing to socket: server has quit or connection broke");
     211            0 :     exit(-1);
     212              :   }
     213            0 : }
     214              : 
     215              : /*******************************************************************************
     216              :  * \brief Reads from a socket.
     217              :  * \param psockfd The id of the socket that will be read from.
     218              :  * \param data    The storage array for data read from the socket.
     219              :  * \param plen    The length of the data in bytes.
     220              :  ******************************************************************************/
     221            0 : void readbuffer(int *psockfd, char *data, int *plen) {
     222            0 :   int n, nr;
     223            0 :   int sockfd = *psockfd;
     224            0 :   int len = *plen;
     225              : 
     226            0 :   n = nr = read(sockfd, data, len);
     227              : 
     228            0 :   while (nr > 0 && n < len) {
     229            0 :     nr = read(sockfd, &data[n], len - n);
     230            0 :     n += nr;
     231              :   }
     232              : 
     233            0 :   if (n == 0) {
     234            0 :     perror("Error reading from socket: server has quit or connection broke");
     235            0 :     exit(-1);
     236              :   }
     237            0 : }
     238              : 
     239              : /*******************************************************************************
     240              :  * \brief Listens to a socket.
     241              :  * \param psockfd The id of the socket to listen.
     242              :  * \param n       An integer that determines the number of requests that will
     243              :  *                be queued before further requests are refused.
     244              :  ******************************************************************************/
     245            0 : void listen_socket(int *psockfd, int *backlog) {
     246              : 
     247            0 :   if (listen(*psockfd, *backlog) < 0) {
     248            0 :     perror("Error listening socket");
     249            0 :     exit(-1);
     250            0 :   };
     251            0 : }
     252              : 
     253              : /*******************************************************************************
     254              :  * \brief Listens to a socket.
     255              :  * \param psockfd   The id of the socket to listen.
     256              :  * \param pclientfd The id of the accepted socket.
     257              :  ******************************************************************************/
     258            0 : void accept_socket(int *psockfd, int *pclientfd) {
     259              : 
     260            0 :   int client_fd = accept(*psockfd, NULL, NULL);
     261              : 
     262            0 :   *pclientfd = client_fd;
     263            0 : }
     264              : 
     265              : /*******************************************************************************
     266              :  * \brief Closes a socket.
     267              :  * \param psockfd The id of the socket to close.
     268              :  ******************************************************************************/
     269            0 : void close_socket(int *psockfd) { close(*psockfd); }
     270              : 
     271              : /*******************************************************************************
     272              :  * \brief Removes a socket file.
     273              :  * \param hostname The name of the socket file to remove.
     274              :  ******************************************************************************/
     275            0 : void remove_socket_file(char *host) { remove(host); }
     276              : 
     277              : /*******************************************************************************
     278              :  * \brief Mini-wrapper to nanosleep
     279              :  * \param dsec number of seconds to wait (float values accepted)
     280              :  ******************************************************************************/
     281            0 : void uwait(double *dsec) {
     282            0 :   struct timespec wt, rem;
     283            0 :   wt.tv_sec = floor(*dsec);
     284            0 :   wt.tv_nsec = (*dsec - wt.tv_sec) * 1000000000;
     285            0 :   nanosleep(&wt, &rem);
     286            0 : }
     287              : 
     288              : #endif
        

Generated by: LCOV version 2.0-1