blob: 15987ff4bef42f78cecc17f4e6aa4c0f0ab4002e [file] [log] [blame]
Ravi Tejace1c96f2020-10-05 23:13:01 -05001#include "utils.hpp"
2
George Liuc453e162022-12-21 17:16:23 +08003#include <libpldm/base.h>
Ravi Tejace1c96f2020-10-05 23:13:01 -05004#include <sys/socket.h>
5#include <sys/types.h>
6#include <sys/un.h>
7#include <unistd.h>
8
9#include <iostream>
10
11namespace pldm
12{
13namespace responder
14{
15namespace utils
16{
Ravi Tejace1c96f2020-10-05 23:13:01 -050017int setupUnixSocket(const std::string& socketInterface)
18{
19 int sock;
20 struct sockaddr_un addr;
21 memset(&addr, 0, sizeof(addr));
22 addr.sun_family = AF_UNIX;
23 if (strnlen(socketInterface.c_str(), sizeof(addr.sun_path)) ==
24 sizeof(addr.sun_path))
25 {
26 std::cerr << "setupUnixSocket: UNIX socket path too long" << std::endl;
27 return -1;
28 }
29
30 strncpy(addr.sun_path, socketInterface.c_str(), sizeof(addr.sun_path) - 1);
31
32 if ((sock = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0)) == -1)
33 {
34 std::cerr << "setupUnixSocket: socket() call failed" << std::endl;
35 return -1;
36 }
37
38 if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1)
39 {
Jayashankar Padathe64f5522022-09-28 21:30:24 -050040 std::cerr << "setupUnixSocket: bind() call failed with errno " << errno
41 << std::endl;
Ravi Tejace1c96f2020-10-05 23:13:01 -050042 close(sock);
43 return -1;
44 }
45
46 if (listen(sock, 1) == -1)
47 {
48 std::cerr << "setupUnixSocket: listen() call failed" << std::endl;
49 close(sock);
50 return -1;
51 }
52
53 fd_set rfd;
54 struct timeval tv;
55 tv.tv_sec = 1;
56 tv.tv_usec = 0;
57
58 FD_ZERO(&rfd);
59 FD_SET(sock, &rfd);
60 int nfd = sock + 1;
Andrew Geisslerefbb5942020-12-15 10:12:30 -060061 int fd = -1;
Ravi Tejace1c96f2020-10-05 23:13:01 -050062
63 int retval = select(nfd, &rfd, NULL, NULL, &tv);
64 if (retval < 0)
65 {
66 std::cerr << "setupUnixSocket: select call failed " << errno
67 << std::endl;
68 close(sock);
69 return -1;
70 }
71
72 if ((retval > 0) && (FD_ISSET(sock, &rfd)))
73 {
74 fd = accept(sock, NULL, NULL);
75 if (fd < 0)
76 {
77 std::cerr << "setupUnixSocket: accept() call failed " << errno
78 << std::endl;
79 close(sock);
80 return -1;
81 }
82 close(sock);
83 }
84 return fd;
85}
86
87int writeToUnixSocket(const int sock, const char* buf, const uint64_t blockSize)
88{
89 uint64_t i;
90 int nwrite = 0;
91
92 for (i = 0; i < blockSize; i = i + nwrite)
93 {
Ravi Tejace1c96f2020-10-05 23:13:01 -050094 fd_set wfd;
95 struct timeval tv;
96 tv.tv_sec = 1;
97 tv.tv_usec = 0;
98
99 FD_ZERO(&wfd);
100 FD_SET(sock, &wfd);
101 int nfd = sock + 1;
102
103 int retval = select(nfd, NULL, &wfd, NULL, &tv);
104 if (retval < 0)
105 {
106 std::cerr << "writeToUnixSocket: select call failed " << errno
107 << std::endl;
108 close(sock);
109 return -1;
110 }
111 if (retval == 0)
112 {
113 nwrite = 0;
114 continue;
115 }
116 if ((retval > 0) && (FD_ISSET(sock, &wfd)))
117 {
118 nwrite = write(sock, buf + i, blockSize - i);
119 if (nwrite < 0)
120 {
121 if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
122 {
123 std::cerr << "writeToUnixSocket: Write call failed with "
124 "EAGAIN or EWOULDBLOCK or EINTR"
125 << std::endl;
126 nwrite = 0;
127 continue;
128 }
129 std::cerr << "writeToUnixSocket: Failed to write" << std::endl;
130 close(sock);
131 return -1;
132 }
133 }
134 else
135 {
136 nwrite = 0;
137 }
138 }
139 return 0;
140}
141
142} // namespace utils
143} // namespace responder
144} // namespace pldm