LCOV - code coverage report
Current view: top level - src - sockets.c (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:936074a) Lines: 0.0 % 105 0
Test Date: 2025-12-04 06:27:48 Functions: 0.0 % 9 0

            Line data    Source code
       1              : /*----------------------------------------------------------------------------*/
       2              : /*  CP2K: A general program to perform molecular dynamics simulations         */
       3              : /*  Copyright 2000-2025 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.
      65              :  * \note  Fortran passes an extra argument for the string length, but this is
      66              :  *        ignored here for C compatibility.
      67              :  ******************************************************************************/
      68            0 : void open_connect_socket(int *psockfd, int *inet, int *port, char *host) {
      69            0 :   int sockfd, ai_err;
      70              : 
      71            0 :   if (*inet > 0) { // creates an internet socket
      72              : 
      73              :     // fetches information on the host
      74            0 :     struct addrinfo hints, *res;
      75            0 :     char service[256];
      76              : 
      77            0 :     memset(&hints, 0, sizeof(hints));
      78            0 :     hints.ai_socktype = SOCK_STREAM;
      79            0 :     hints.ai_family = AF_INET;
      80            0 :     hints.ai_flags = AI_PASSIVE;
      81              : 
      82            0 :     sprintf(service, "%d", *port); // convert the port number to a string
      83            0 :     ai_err = getaddrinfo(host, service, &hints, &res);
      84            0 :     if (ai_err != 0) {
      85            0 :       perror("Error fetching host data. Wrong host name?");
      86            0 :       exit(-1);
      87              :     }
      88              : 
      89              :     // creates socket
      90            0 :     sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
      91            0 :     if (sockfd < 0) {
      92            0 :       perror("Error opening socket");
      93            0 :       exit(-1);
      94              :     }
      95              : 
      96              :     // makes connection
      97            0 :     if (connect(sockfd, res->ai_addr, res->ai_addrlen) < 0) {
      98            0 :       perror("Error opening INET socket: wrong port or server unreachable");
      99            0 :       exit(-1);
     100              :     }
     101            0 :     freeaddrinfo(res);
     102              :   } else { // creates a unix socket
     103            0 :     struct sockaddr_un serv_addr;
     104              : 
     105              :     // fills up details of the socket address
     106            0 :     memset(&serv_addr, 0, sizeof(serv_addr));
     107            0 :     serv_addr.sun_family = AF_UNIX;
     108            0 :     strcpy(serv_addr.sun_path, "/tmp/qiskit_");
     109            0 :     strcpy(serv_addr.sun_path + 12, host);
     110              : 
     111              :     // creates the socket
     112            0 :     sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
     113              : 
     114              :     // connects
     115            0 :     if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
     116            0 :       perror(
     117              :           "Error opening UNIX socket: path unavailable, or already existing");
     118            0 :       exit(-1);
     119              :     }
     120              :   }
     121              : 
     122            0 :   *psockfd = sockfd;
     123            0 : }
     124              : 
     125              : /*******************************************************************************
     126              :  * \brief Opens and binds a socket.
     127              :  * \param psockfd The id of the socket that will be created.
     128              :  * \param inet    An integer that determines whether the socket will be an inet
     129              :  *                or unix domain socket. Gives unix if 0, inet otherwise.
     130              :  * \param port    The port number for the socket to be created. Low numbers are
     131              :  *                often reserved for important channels, so use of numbers of 4
     132              :  *                or more digits is recommended.
     133              :  * \param host    The name of the host server.
     134              :  * \note  Fortran passes an extra argument for the string length, but this is
     135              :  *        ignored here for C compatibility.
     136              :  ******************************************************************************/
     137            0 : void open_bind_socket(int *psockfd, int *inet, int *port, char *host) {
     138            0 :   int sockfd, ai_err;
     139              : 
     140            0 :   if (*inet > 0) { // creates an internet socket
     141              : 
     142              :     // fetches information on the host
     143            0 :     struct addrinfo hints, *res;
     144            0 :     char service[256];
     145              : 
     146            0 :     memset(&hints, 0, sizeof(hints));
     147            0 :     hints.ai_socktype = SOCK_STREAM;
     148            0 :     hints.ai_family = AF_INET;
     149            0 :     hints.ai_flags = AI_PASSIVE;
     150              : 
     151            0 :     sprintf(service, "%d", *port); // convert the port number to a string
     152            0 :     ai_err = getaddrinfo(host, service, &hints, &res);
     153            0 :     if (ai_err != 0) {
     154            0 :       perror("Error fetching host data. Wrong host name?");
     155            0 :       exit(-1);
     156              :     }
     157              : 
     158              :     // creates socket
     159            0 :     sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
     160            0 :     if (sockfd < 0) {
     161            0 :       perror("Error opening socket");
     162            0 :       exit(-1);
     163              :     }
     164              : 
     165              :     // binds
     166            0 :     if (bind(sockfd, res->ai_addr, res->ai_addrlen) < 0) {
     167            0 :       perror("Error binding INET socket: wrong port or server unreachable");
     168            0 :       exit(-1);
     169              :     }
     170            0 :     freeaddrinfo(res);
     171              :   } else { // creates a unix socket
     172            0 :     struct sockaddr_un serv_addr;
     173              : 
     174              :     // fills up details of the socket address
     175            0 :     memset(&serv_addr, 0, sizeof(serv_addr));
     176            0 :     serv_addr.sun_family = AF_UNIX;
     177            0 :     strcpy(serv_addr.sun_path, host);
     178              : 
     179              :     // creates the socket
     180            0 :     sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
     181              : 
     182            0 :     remove(serv_addr.sun_path);
     183              : 
     184              :     // binds
     185            0 :     if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
     186            0 :       perror(
     187              :           "Error binding UNIX socket: path unavailable, or already existing");
     188            0 :       exit(-1);
     189              :     }
     190              :   }
     191              : 
     192            0 :   *psockfd = sockfd;
     193            0 : }
     194              : 
     195              : /*******************************************************************************
     196              :  * \brief Writes to a socket.
     197              :  * \param psockfd The id of the socket that will be written to.
     198              :  * \param data    The data to be written to the socket.
     199              :  * \param plen    The length of the data in bytes.
     200              :  ******************************************************************************/
     201            0 : void writebuffer(int *psockfd, char *data, int *plen) {
     202            0 :   int n;
     203            0 :   int sockfd = *psockfd;
     204            0 :   int len = *plen;
     205              : 
     206            0 :   n = write(sockfd, data, len);
     207            0 :   if (n < 0) {
     208            0 :     perror("Error writing to socket: server has quit or connection broke");
     209            0 :     exit(-1);
     210              :   }
     211            0 : }
     212              : 
     213              : /*******************************************************************************
     214              :  * \brief Reads from a socket.
     215              :  * \param psockfd The id of the socket that will be read from.
     216              :  * \param data    The storage array for data read from the socket.
     217              :  * \param plen    The length of the data in bytes.
     218              :  ******************************************************************************/
     219            0 : void readbuffer(int *psockfd, char *data, int *plen) {
     220            0 :   int n, nr;
     221            0 :   int sockfd = *psockfd;
     222            0 :   int len = *plen;
     223              : 
     224            0 :   n = nr = read(sockfd, data, len);
     225              : 
     226            0 :   while (nr > 0 && n < len) {
     227            0 :     nr = read(sockfd, &data[n], len - n);
     228            0 :     n += nr;
     229              :   }
     230              : 
     231            0 :   if (n == 0) {
     232            0 :     perror("Error reading from socket: server has quit or connection broke");
     233            0 :     exit(-1);
     234              :   }
     235            0 : }
     236              : 
     237              : /*******************************************************************************
     238              :  * \brief Listens to a socket.
     239              :  * \param psockfd The id of the socket to listen.
     240              :  * \param n       An integer that determines the number of requests that will
     241              :  *                be queued before further requests are refused.
     242              :  ******************************************************************************/
     243            0 : void listen_socket(int *psockfd, int *backlog) {
     244              : 
     245            0 :   if (listen(*psockfd, *backlog) < 0) {
     246            0 :     perror("Error listening socket");
     247            0 :     exit(-1);
     248            0 :   };
     249            0 : }
     250              : 
     251              : /*******************************************************************************
     252              :  * \brief Listens to a socket.
     253              :  * \param psockfd   The id of the socket to listen.
     254              :  * \param pclientfd The id of the accepted socket.
     255              :  ******************************************************************************/
     256            0 : void accept_socket(int *psockfd, int *pclientfd) {
     257              : 
     258            0 :   int client_fd = accept(*psockfd, NULL, NULL);
     259              : 
     260            0 :   *pclientfd = client_fd;
     261            0 : }
     262              : 
     263              : /*******************************************************************************
     264              :  * \brief Closes a socket.
     265              :  * \param psockfd The id of the socket to close.
     266              :  ******************************************************************************/
     267            0 : void close_socket(int *psockfd) { close(*psockfd); }
     268              : 
     269              : /*******************************************************************************
     270              :  * \brief Removes a socket file.
     271              :  * \param hostname The name of the socket file to remove.
     272              :  ******************************************************************************/
     273            0 : void remove_socket_file(char *host) { remove(host); }
     274              : 
     275              : /*******************************************************************************
     276              :  * \brief Mini-wrapper to nanosleep
     277              :  * \param dsec number of seconds to wait (float values accepted)
     278              :  ******************************************************************************/
     279            0 : void uwait(double *dsec) {
     280            0 :   struct timespec wt, rem;
     281            0 :   wt.tv_sec = floor(*dsec);
     282            0 :   wt.tv_nsec = (*dsec - wt.tv_sec) * 1000000000;
     283            0 :   nanosleep(&wt, &rem);
     284            0 : }
     285              : 
     286              : #endif
        

Generated by: LCOV version 2.0-1