49#include "debug/VIO9P.hh" 50#include "debug/VIO9PData.hh" 51#include "params/VirtIO9PBase.hh" 52#include "params/VirtIO9PDiod.hh" 53#include "params/VirtIO9PProxy.hh" 54#include "params/VirtIO9PSocket.hh" 55#include "sim/system.hh" 56 57struct P9MsgInfo { 58 P9MsgInfo(P9MsgType _type, std::string _name) 59 : type(_type), name(_name) {} 60 61 P9MsgType type; 62 std::string name; 63}; 64 65typedef std::map<P9MsgType, P9MsgInfo> P9MsgInfoMap; 66 67#define P9MSG(type, name) \ 68 { (type), P9MsgInfo((type), "T" # name ) }, \ 69 { (type + 1), P9MsgInfo((type + 1), "R" # name ) } 70 71static const P9MsgInfoMap p9_msg_info { 72 P9MSG(6, LERROR), 73 P9MSG(8, STATFS), 74 P9MSG(12, LOPEN), 75 P9MSG(14, LCREATE), 76 P9MSG(16, SYMLINK), 77 P9MSG(18, MKNOD), 78 P9MSG(20, RENAME), 79 P9MSG(22, READLINK), 80 P9MSG(24, GETATTR), 81 P9MSG(26, SETATTR), 82 P9MSG(30, XATTRWALK), 83 P9MSG(32, XATTRCREATE), 84 P9MSG(40, READDIR), 85 P9MSG(50, FSYNC), 86 P9MSG(52, LOCK), 87 P9MSG(54, GETLOCK), 88 P9MSG(70, LINK), 89 P9MSG(72, MKDIR), 90 P9MSG(74, RENAMEAT), 91 P9MSG(76, UNLINKAT), 92 P9MSG(100, VERSION), 93 P9MSG(102, AUTH), 94 P9MSG(104, ATTACH), 95 P9MSG(106, ERROR), 96 P9MSG(108, FLUSH), 97 P9MSG(110, WALK), 98 P9MSG(112, OPEN), 99 P9MSG(114, CREATE), 100 P9MSG(116, READ), 101 P9MSG(118, WRITE), 102 P9MSG(120, CLUNK), 103 P9MSG(122, REMOVE), 104 P9MSG(124, STAT), 105 P9MSG(126, WSTAT), 106}; 107 108#undef P9MSG 109 110VirtIO9PBase::VirtIO9PBase(Params *params) 111 : VirtIODeviceBase(params, ID_9P, 112 sizeof(Config) + params->tag.size(), 113 F_MOUNT_TAG), 114 queue(params->system->physProxy, params->queueSize, *this) 115{ 116 config.reset((Config *) 117 operator new(configSize)); 118 config->len = htov_legacy(params->tag.size()); 119 memcpy(config->tag, params->tag.c_str(), params->tag.size()); 120 121 registerQueue(queue); 122} 123 124 125VirtIO9PBase::~VirtIO9PBase() 126{ 127} 128 129void 130VirtIO9PBase::readConfig(PacketPtr pkt, Addr cfgOffset) 131{ 132 readConfigBlob(pkt, cfgOffset, (uint8_t *)config.get()); 133} 134 135void 136VirtIO9PBase::FSQueue::onNotifyDescriptor(VirtDescriptor *desc) 137{ 138 DPRINTF(VIO9P, "Got input data descriptor (len: %i)\n", desc->size()); 139 DPRINTF(VIO9P, "\tPending transactions: %i\n", parent.pendingTransactions.size()); 140 141 P9MsgHeader header; 142 desc->chainRead(0, (uint8_t *)&header, sizeof(header)); 143 header = p9toh(header); 144 145 uint8_t data[header.len - sizeof(header)]; 146 desc->chainRead(sizeof(header), data, sizeof(data)); 147 148 // Keep track of pending transactions 149 parent.pendingTransactions[header.tag] = desc; 150 151 DPRINTF(VIO9P, "recvTMsg\n"); 152 parent.dumpMsg(header, data, sizeof(data)); 153 154 // Notify device of message 155 parent.recvTMsg(header, data, sizeof(data)); 156} 157 158void 159VirtIO9PBase::sendRMsg(const P9MsgHeader &header, const uint8_t *data, size_t size) 160{ 161 DPRINTF(VIO9P, "Sending RMsg\n"); 162 dumpMsg(header, data, size); 163 DPRINTF(VIO9P, "\tPending transactions: %i\n", pendingTransactions.size()); 164 assert(header.len >= sizeof(header)); 165 166 VirtDescriptor *main_desc(pendingTransactions[header.tag]); 167 pendingTransactions.erase(header.tag); 168 169 // Find the first output descriptor 170 VirtDescriptor *out_desc(main_desc); 171 while (out_desc && !out_desc->isOutgoing()) 172 out_desc = out_desc->next(); 173 if (!out_desc) 174 panic("sendRMsg: Framing error, no output descriptor.\n"); 175 176 P9MsgHeader header_out(htop9(header)); 177 header_out.len = htop9(sizeof(P9MsgHeader) + size); 178 179 out_desc->chainWrite(0, (uint8_t *)&header_out, sizeof(header_out)); 180 out_desc->chainWrite(sizeof(header_out), data, size); 181 182 queue.produceDescriptor(main_desc, sizeof(P9MsgHeader) + size); 183 kick(); 184} 185 186void 187VirtIO9PBase::dumpMsg(const P9MsgHeader &header, const uint8_t *data, size_t size) 188{ 189#ifndef NDEBUG 190 if (!DTRACE(VIO9P)) 191 return; 192 193 const P9MsgInfoMap::const_iterator it_msg(p9_msg_info.find(header.type)); 194 if (it_msg != p9_msg_info.cend()) { 195 const P9MsgInfo &info(it_msg->second); 196 DPRINTF(VIO9P, "P9Msg[len = %i, type = %s (%i), tag = %i]\n", 197 header.len, info.name, header.type, header.tag); 198 } else { 199 DPRINTF(VIO9P, "P9Msg[len = %i, type = Unknown (%i), tag = %i]\n", 200 header.len, header.type, header.tag); 201 } 202 DDUMP(VIO9PData, data, size); 203#endif 204} 205 206 207VirtIO9PProxy::VirtIO9PProxy(Params *params) 208 : VirtIO9PBase(params), deviceUsed(false) 209{ 210} 211 212VirtIO9PProxy::~VirtIO9PProxy() 213{ 214} 215 216 217void 218VirtIO9PProxy::serialize(CheckpointOut &cp) const 219{ 220 if (deviceUsed) { 221 warn("Serializing VirtIO9Base device after device has been used. It is " 222 "likely that state will be lost, and that the device will cease " 223 "to work!"); 224 } 225 SERIALIZE_SCALAR(deviceUsed); 226 227 VirtIO9PBase::serialize(cp); 228} 229 230void 231VirtIO9PProxy::unserialize(CheckpointIn &cp) 232{ 233 UNSERIALIZE_SCALAR(deviceUsed); 234 235 if (deviceUsed) { 236 warn("Unserializing VirtIO9Base device after device has been used. It is " 237 "likely that state has been lost, and that the device will cease " 238 "to work!"); 239 } 240 VirtIO9PBase::unserialize(cp); 241} 242 243 244void 245VirtIO9PProxy::recvTMsg(const P9MsgHeader &header, 246 const uint8_t *data, size_t size) 247{ 248 deviceUsed = true; 249 assert(header.len == sizeof(header) + size); 250 // While technically not needed, we send the packet as one 251 // contiguous segment to make some packet dissectors happy. 252 uint8_t out[header.len]; 253 P9MsgHeader header_out(htop9(header)); 254 memcpy(out, (uint8_t *)&header_out, sizeof(header_out)); 255 memcpy(out + sizeof(header_out), data, size); 256 writeAll(out, sizeof(header_out) + size); 257} 258 259void 260VirtIO9PProxy::serverDataReady() 261{ 262 P9MsgHeader header; 263 readAll((uint8_t *)&header, sizeof(header)); 264 header = p9toh(header); 265 266 const ssize_t payload_len(header.len - sizeof(header)); 267 if (payload_len < 0) 268 panic("Payload length is negative!\n"); 269 uint8_t data[payload_len]; 270 readAll(data, payload_len); 271 272 sendRMsg(header, data, payload_len); 273} 274 275 276void 277VirtIO9PProxy::readAll(uint8_t *data, size_t len) 278{ 279 while (len) { 280 ssize_t ret; 281 while ((ret = read(data, len)) == -EAGAIN) 282 ; 283 if (ret < 0) 284 panic("readAll: Read failed: %i\n", -ret); 285 286 len -= ret; 287 data += ret; 288 } 289} 290 291void 292VirtIO9PProxy::writeAll(const uint8_t *data, size_t len) 293{ 294 while (len) { 295 ssize_t ret; 296 while ((ret = write(data, len)) == -EAGAIN) 297 ; 298 if (ret < 0) 299 panic("writeAll: write failed: %i\n", -ret); 300 301 len -= ret; 302 data += ret; 303 } 304} 305 306 307 308VirtIO9PDiod::VirtIO9PDiod(Params *params) 309 : VirtIO9PProxy(params), 310 fd_to_diod(-1), fd_from_diod(-1), diod_pid(-1) 311{ 312} 313 314VirtIO9PDiod::~VirtIO9PDiod() 315{ 316} 317 318void 319VirtIO9PDiod::startup() 320{ 321 startDiod(); 322 dataEvent.reset(new DiodDataEvent(*this, fd_from_diod, POLLIN)); 323 pollQueue.schedule(dataEvent.get()); 324} 325 326void 327VirtIO9PDiod::startDiod() 328{ 329 const Params *p(dynamic_cast<const Params *>(params())); 330 int pipe_rfd[2]; 331 int pipe_wfd[2]; 332 const int DIOD_RFD = 3; 333 const int DIOD_WFD = 4; 334 335 const char *diod(p->diod.c_str()); 336
| 53#include "debug/VIO9P.hh" 54#include "debug/VIO9PData.hh" 55#include "params/VirtIO9PBase.hh" 56#include "params/VirtIO9PDiod.hh" 57#include "params/VirtIO9PProxy.hh" 58#include "params/VirtIO9PSocket.hh" 59#include "sim/system.hh" 60 61struct P9MsgInfo { 62 P9MsgInfo(P9MsgType _type, std::string _name) 63 : type(_type), name(_name) {} 64 65 P9MsgType type; 66 std::string name; 67}; 68 69typedef std::map<P9MsgType, P9MsgInfo> P9MsgInfoMap; 70 71#define P9MSG(type, name) \ 72 { (type), P9MsgInfo((type), "T" # name ) }, \ 73 { (type + 1), P9MsgInfo((type + 1), "R" # name ) } 74 75static const P9MsgInfoMap p9_msg_info { 76 P9MSG(6, LERROR), 77 P9MSG(8, STATFS), 78 P9MSG(12, LOPEN), 79 P9MSG(14, LCREATE), 80 P9MSG(16, SYMLINK), 81 P9MSG(18, MKNOD), 82 P9MSG(20, RENAME), 83 P9MSG(22, READLINK), 84 P9MSG(24, GETATTR), 85 P9MSG(26, SETATTR), 86 P9MSG(30, XATTRWALK), 87 P9MSG(32, XATTRCREATE), 88 P9MSG(40, READDIR), 89 P9MSG(50, FSYNC), 90 P9MSG(52, LOCK), 91 P9MSG(54, GETLOCK), 92 P9MSG(70, LINK), 93 P9MSG(72, MKDIR), 94 P9MSG(74, RENAMEAT), 95 P9MSG(76, UNLINKAT), 96 P9MSG(100, VERSION), 97 P9MSG(102, AUTH), 98 P9MSG(104, ATTACH), 99 P9MSG(106, ERROR), 100 P9MSG(108, FLUSH), 101 P9MSG(110, WALK), 102 P9MSG(112, OPEN), 103 P9MSG(114, CREATE), 104 P9MSG(116, READ), 105 P9MSG(118, WRITE), 106 P9MSG(120, CLUNK), 107 P9MSG(122, REMOVE), 108 P9MSG(124, STAT), 109 P9MSG(126, WSTAT), 110}; 111 112#undef P9MSG 113 114VirtIO9PBase::VirtIO9PBase(Params *params) 115 : VirtIODeviceBase(params, ID_9P, 116 sizeof(Config) + params->tag.size(), 117 F_MOUNT_TAG), 118 queue(params->system->physProxy, params->queueSize, *this) 119{ 120 config.reset((Config *) 121 operator new(configSize)); 122 config->len = htov_legacy(params->tag.size()); 123 memcpy(config->tag, params->tag.c_str(), params->tag.size()); 124 125 registerQueue(queue); 126} 127 128 129VirtIO9PBase::~VirtIO9PBase() 130{ 131} 132 133void 134VirtIO9PBase::readConfig(PacketPtr pkt, Addr cfgOffset) 135{ 136 readConfigBlob(pkt, cfgOffset, (uint8_t *)config.get()); 137} 138 139void 140VirtIO9PBase::FSQueue::onNotifyDescriptor(VirtDescriptor *desc) 141{ 142 DPRINTF(VIO9P, "Got input data descriptor (len: %i)\n", desc->size()); 143 DPRINTF(VIO9P, "\tPending transactions: %i\n", parent.pendingTransactions.size()); 144 145 P9MsgHeader header; 146 desc->chainRead(0, (uint8_t *)&header, sizeof(header)); 147 header = p9toh(header); 148 149 uint8_t data[header.len - sizeof(header)]; 150 desc->chainRead(sizeof(header), data, sizeof(data)); 151 152 // Keep track of pending transactions 153 parent.pendingTransactions[header.tag] = desc; 154 155 DPRINTF(VIO9P, "recvTMsg\n"); 156 parent.dumpMsg(header, data, sizeof(data)); 157 158 // Notify device of message 159 parent.recvTMsg(header, data, sizeof(data)); 160} 161 162void 163VirtIO9PBase::sendRMsg(const P9MsgHeader &header, const uint8_t *data, size_t size) 164{ 165 DPRINTF(VIO9P, "Sending RMsg\n"); 166 dumpMsg(header, data, size); 167 DPRINTF(VIO9P, "\tPending transactions: %i\n", pendingTransactions.size()); 168 assert(header.len >= sizeof(header)); 169 170 VirtDescriptor *main_desc(pendingTransactions[header.tag]); 171 pendingTransactions.erase(header.tag); 172 173 // Find the first output descriptor 174 VirtDescriptor *out_desc(main_desc); 175 while (out_desc && !out_desc->isOutgoing()) 176 out_desc = out_desc->next(); 177 if (!out_desc) 178 panic("sendRMsg: Framing error, no output descriptor.\n"); 179 180 P9MsgHeader header_out(htop9(header)); 181 header_out.len = htop9(sizeof(P9MsgHeader) + size); 182 183 out_desc->chainWrite(0, (uint8_t *)&header_out, sizeof(header_out)); 184 out_desc->chainWrite(sizeof(header_out), data, size); 185 186 queue.produceDescriptor(main_desc, sizeof(P9MsgHeader) + size); 187 kick(); 188} 189 190void 191VirtIO9PBase::dumpMsg(const P9MsgHeader &header, const uint8_t *data, size_t size) 192{ 193#ifndef NDEBUG 194 if (!DTRACE(VIO9P)) 195 return; 196 197 const P9MsgInfoMap::const_iterator it_msg(p9_msg_info.find(header.type)); 198 if (it_msg != p9_msg_info.cend()) { 199 const P9MsgInfo &info(it_msg->second); 200 DPRINTF(VIO9P, "P9Msg[len = %i, type = %s (%i), tag = %i]\n", 201 header.len, info.name, header.type, header.tag); 202 } else { 203 DPRINTF(VIO9P, "P9Msg[len = %i, type = Unknown (%i), tag = %i]\n", 204 header.len, header.type, header.tag); 205 } 206 DDUMP(VIO9PData, data, size); 207#endif 208} 209 210 211VirtIO9PProxy::VirtIO9PProxy(Params *params) 212 : VirtIO9PBase(params), deviceUsed(false) 213{ 214} 215 216VirtIO9PProxy::~VirtIO9PProxy() 217{ 218} 219 220 221void 222VirtIO9PProxy::serialize(CheckpointOut &cp) const 223{ 224 if (deviceUsed) { 225 warn("Serializing VirtIO9Base device after device has been used. It is " 226 "likely that state will be lost, and that the device will cease " 227 "to work!"); 228 } 229 SERIALIZE_SCALAR(deviceUsed); 230 231 VirtIO9PBase::serialize(cp); 232} 233 234void 235VirtIO9PProxy::unserialize(CheckpointIn &cp) 236{ 237 UNSERIALIZE_SCALAR(deviceUsed); 238 239 if (deviceUsed) { 240 warn("Unserializing VirtIO9Base device after device has been used. It is " 241 "likely that state has been lost, and that the device will cease " 242 "to work!"); 243 } 244 VirtIO9PBase::unserialize(cp); 245} 246 247 248void 249VirtIO9PProxy::recvTMsg(const P9MsgHeader &header, 250 const uint8_t *data, size_t size) 251{ 252 deviceUsed = true; 253 assert(header.len == sizeof(header) + size); 254 // While technically not needed, we send the packet as one 255 // contiguous segment to make some packet dissectors happy. 256 uint8_t out[header.len]; 257 P9MsgHeader header_out(htop9(header)); 258 memcpy(out, (uint8_t *)&header_out, sizeof(header_out)); 259 memcpy(out + sizeof(header_out), data, size); 260 writeAll(out, sizeof(header_out) + size); 261} 262 263void 264VirtIO9PProxy::serverDataReady() 265{ 266 P9MsgHeader header; 267 readAll((uint8_t *)&header, sizeof(header)); 268 header = p9toh(header); 269 270 const ssize_t payload_len(header.len - sizeof(header)); 271 if (payload_len < 0) 272 panic("Payload length is negative!\n"); 273 uint8_t data[payload_len]; 274 readAll(data, payload_len); 275 276 sendRMsg(header, data, payload_len); 277} 278 279 280void 281VirtIO9PProxy::readAll(uint8_t *data, size_t len) 282{ 283 while (len) { 284 ssize_t ret; 285 while ((ret = read(data, len)) == -EAGAIN) 286 ; 287 if (ret < 0) 288 panic("readAll: Read failed: %i\n", -ret); 289 290 len -= ret; 291 data += ret; 292 } 293} 294 295void 296VirtIO9PProxy::writeAll(const uint8_t *data, size_t len) 297{ 298 while (len) { 299 ssize_t ret; 300 while ((ret = write(data, len)) == -EAGAIN) 301 ; 302 if (ret < 0) 303 panic("writeAll: write failed: %i\n", -ret); 304 305 len -= ret; 306 data += ret; 307 } 308} 309 310 311 312VirtIO9PDiod::VirtIO9PDiod(Params *params) 313 : VirtIO9PProxy(params), 314 fd_to_diod(-1), fd_from_diod(-1), diod_pid(-1) 315{ 316} 317 318VirtIO9PDiod::~VirtIO9PDiod() 319{ 320} 321 322void 323VirtIO9PDiod::startup() 324{ 325 startDiod(); 326 dataEvent.reset(new DiodDataEvent(*this, fd_from_diod, POLLIN)); 327 pollQueue.schedule(dataEvent.get()); 328} 329 330void 331VirtIO9PDiod::startDiod() 332{ 333 const Params *p(dynamic_cast<const Params *>(params())); 334 int pipe_rfd[2]; 335 int pipe_wfd[2]; 336 const int DIOD_RFD = 3; 337 const int DIOD_WFD = 4; 338 339 const char *diod(p->diod.c_str()); 340
|
365 } else { 366 close(pipe_rfd[0]); 367 close(pipe_wfd[1]); 368 } 369 370#undef DIOD_RFD 371#undef DIOD_WFD 372} 373 374ssize_t 375VirtIO9PDiod::read(uint8_t *data, size_t len) 376{ 377 assert(fd_from_diod != -1); 378 const int ret(::read(fd_from_diod, (void *)data, len)); 379 return ret < 0 ? -errno : ret; 380} 381 382ssize_t 383VirtIO9PDiod::write(const uint8_t *data, size_t len) 384{ 385 assert(fd_to_diod != -1); 386 const int ret(::write(fd_to_diod, (const void *)data, len)); 387 return ret < 0 ? -errno : ret; 388} 389 390void 391VirtIO9PDiod::DiodDataEvent::process(int revent) 392{ 393 parent.serverDataReady(); 394} 395 396VirtIO9PDiod * 397VirtIO9PDiodParams::create() 398{ 399 return new VirtIO9PDiod(this); 400} 401 402 403 404 405VirtIO9PSocket::VirtIO9PSocket(Params *params) 406 : VirtIO9PProxy(params), fdSocket(-1) 407{ 408} 409 410VirtIO9PSocket::~VirtIO9PSocket() 411{ 412} 413 414void 415VirtIO9PSocket::startup() 416{ 417 connectSocket(); 418 dataEvent.reset(new SocketDataEvent(*this, fdSocket, POLLIN)); 419 pollQueue.schedule(dataEvent.get()); 420} 421 422void 423VirtIO9PSocket::connectSocket() 424{ 425 const Params &p(dynamic_cast<const Params &>(*params())); 426 427 int ret; 428 struct addrinfo hints, *result; 429 memset(&hints, 0, sizeof(hints)); 430 hints.ai_family = AF_UNSPEC; 431 hints.ai_socktype = SOCK_STREAM; 432 hints.ai_flags = 0; 433 hints.ai_protocol = 0; 434 435 if ((ret = getaddrinfo(p.server.c_str(), p.port.c_str(), 436 &hints, &result)) != 0) 437 panic("getaddrinfo: %s\n", gai_strerror(ret)); 438 439 DPRINTF(VIO9P, "Connecting to 9p server '%s'.\n", p.server); 440 for (struct addrinfo *rp = result; rp; rp = rp->ai_next) { 441 fdSocket = socket(rp->ai_family, rp->ai_socktype, 442 rp->ai_protocol); 443 if (fdSocket == -1) { 444 continue; 445 } else if (connect(fdSocket, rp->ai_addr, rp->ai_addrlen) != -1) { 446 break; 447 } else { 448 close(fdSocket); 449 fdSocket = -1; 450 } 451 } 452 453 freeaddrinfo(result); 454 455 if (fdSocket == -1) 456 panic("Failed to connect to 9p server (%s:%s)", p.server, p.port); 457} 458 459void 460VirtIO9PSocket::socketDisconnect() 461{ 462 panic("9P Socket disconnected!\n"); 463} 464 465ssize_t 466VirtIO9PSocket::read(uint8_t *data, size_t len) 467{ 468 assert(fdSocket != -1); 469 int ret; 470 471 ret = ::recv(fdSocket, (void *)data, len, 0); 472 if (ret == 0) 473 socketDisconnect(); 474 475 return ret < 0 ? -errno : ret; 476} 477 478ssize_t 479VirtIO9PSocket::write(const uint8_t *data, size_t len) 480{ 481 assert(fdSocket != -1); 482 int ret(::send(fdSocket, (const void *)data, len, 0)); 483 return ret < 0 ? -errno : ret; 484} 485 486void 487VirtIO9PSocket::SocketDataEvent::process(int revent) 488{ 489 parent.serverDataReady(); 490} 491 492 493VirtIO9PSocket * 494VirtIO9PSocketParams::create() 495{ 496 return new VirtIO9PSocket(this); 497}
| 400 } else { 401 close(pipe_rfd[0]); 402 close(pipe_wfd[1]); 403 } 404 405#undef DIOD_RFD 406#undef DIOD_WFD 407} 408 409ssize_t 410VirtIO9PDiod::read(uint8_t *data, size_t len) 411{ 412 assert(fd_from_diod != -1); 413 const int ret(::read(fd_from_diod, (void *)data, len)); 414 return ret < 0 ? -errno : ret; 415} 416 417ssize_t 418VirtIO9PDiod::write(const uint8_t *data, size_t len) 419{ 420 assert(fd_to_diod != -1); 421 const int ret(::write(fd_to_diod, (const void *)data, len)); 422 return ret < 0 ? -errno : ret; 423} 424 425void 426VirtIO9PDiod::DiodDataEvent::process(int revent) 427{ 428 parent.serverDataReady(); 429} 430 431VirtIO9PDiod * 432VirtIO9PDiodParams::create() 433{ 434 return new VirtIO9PDiod(this); 435} 436 437 438 439 440VirtIO9PSocket::VirtIO9PSocket(Params *params) 441 : VirtIO9PProxy(params), fdSocket(-1) 442{ 443} 444 445VirtIO9PSocket::~VirtIO9PSocket() 446{ 447} 448 449void 450VirtIO9PSocket::startup() 451{ 452 connectSocket(); 453 dataEvent.reset(new SocketDataEvent(*this, fdSocket, POLLIN)); 454 pollQueue.schedule(dataEvent.get()); 455} 456 457void 458VirtIO9PSocket::connectSocket() 459{ 460 const Params &p(dynamic_cast<const Params &>(*params())); 461 462 int ret; 463 struct addrinfo hints, *result; 464 memset(&hints, 0, sizeof(hints)); 465 hints.ai_family = AF_UNSPEC; 466 hints.ai_socktype = SOCK_STREAM; 467 hints.ai_flags = 0; 468 hints.ai_protocol = 0; 469 470 if ((ret = getaddrinfo(p.server.c_str(), p.port.c_str(), 471 &hints, &result)) != 0) 472 panic("getaddrinfo: %s\n", gai_strerror(ret)); 473 474 DPRINTF(VIO9P, "Connecting to 9p server '%s'.\n", p.server); 475 for (struct addrinfo *rp = result; rp; rp = rp->ai_next) { 476 fdSocket = socket(rp->ai_family, rp->ai_socktype, 477 rp->ai_protocol); 478 if (fdSocket == -1) { 479 continue; 480 } else if (connect(fdSocket, rp->ai_addr, rp->ai_addrlen) != -1) { 481 break; 482 } else { 483 close(fdSocket); 484 fdSocket = -1; 485 } 486 } 487 488 freeaddrinfo(result); 489 490 if (fdSocket == -1) 491 panic("Failed to connect to 9p server (%s:%s)", p.server, p.port); 492} 493 494void 495VirtIO9PSocket::socketDisconnect() 496{ 497 panic("9P Socket disconnected!\n"); 498} 499 500ssize_t 501VirtIO9PSocket::read(uint8_t *data, size_t len) 502{ 503 assert(fdSocket != -1); 504 int ret; 505 506 ret = ::recv(fdSocket, (void *)data, len, 0); 507 if (ret == 0) 508 socketDisconnect(); 509 510 return ret < 0 ? -errno : ret; 511} 512 513ssize_t 514VirtIO9PSocket::write(const uint8_t *data, size_t len) 515{ 516 assert(fdSocket != -1); 517 int ret(::send(fdSocket, (const void *)data, len, 0)); 518 return ret < 0 ? -errno : ret; 519} 520 521void 522VirtIO9PSocket::SocketDataEvent::process(int revent) 523{ 524 parent.serverDataReady(); 525} 526 527 528VirtIO9PSocket * 529VirtIO9PSocketParams::create() 530{ 531 return new VirtIO9PSocket(this); 532}
|