status_t BNetEndpoint::Bind(const BNetAddress& address) { if (fSocket < 0 && _SetupSocket() != B_OK) return fStatus; struct sockaddr_in addr; status_t status = address.GetAddr(addr); if (status != B_OK) return status; if (bind(fSocket, (struct sockaddr *)&addr, sizeof(addr)) < 0) { fStatus = errno; Close(); return B_ERROR; } socklen_t addrSize = sizeof(addr); if (getsockname(fSocket, (struct sockaddr *)&addr, &addrSize) < 0) { fStatus = errno; Close(); return B_ERROR; } fAddr.SetTo(addr); return B_OK; }
status_t BNetEndpoint::Connect(const BNetAddress& address) { if (fSocket < 0 && _SetupSocket() != B_OK) return fStatus; sockaddr_in addr; if (address.GetAddr(addr) != B_OK) return B_ERROR; if (connect(fSocket, (sockaddr *) &addr, sizeof(addr)) < 0) { Close(); fStatus = errno; return B_ERROR; } socklen_t addrSize = sizeof(addr); if (getpeername(fSocket, (sockaddr *) &addr, &addrSize) < 0) { Close(); fStatus = errno; return B_ERROR; } fPeer.SetTo(addr); return B_OK; }
int32 BNetEndpoint::SendTo(const void* buffer, size_t length, const BNetAddress& address, int flags) { if (fSocket < 0 && _SetupSocket() != B_OK) return fStatus; struct sockaddr_in addr; if (address.GetAddr(addr) != B_OK) return B_ERROR; ssize_t bytesSent = sendto(fSocket, buffer, length, flags, (struct sockaddr *) &addr, sizeof(addr)); if (bytesSent < 0) fStatus = errno; return bytesSent; }
bool FtpClient::_OpenDataConnection() { string host, cmd, replyString; unsigned short port; BNetAddress addr; int i, code, codeType; bool rc = false; struct sockaddr_in sa; delete fData; fData = 0; fData = new BNetEndpoint; if (_TestState(ftp_passive)) { // Here we send a "pasv" command and connect to the remote server // on the port it sends back to us cmd = "PASV"; if (_SendRequest(cmd)) { if (_GetReply(replyString, code, codeType)) { if (codeType == 2) { // It should give us something like: // "227 Entering Passive Mode (192,168,1,1,10,187)" int paddr[6]; unsigned char ucaddr[6]; i = replyString.find('('); i++; replyString = replyString.substr(i, replyString.find(')') - i); if (sscanf(replyString.c_str(), "%d,%d,%d,%d,%d,%d", &paddr[0], &paddr[1], &paddr[2], &paddr[3], &paddr[4], &paddr[5]) != 6) { // cannot do passive. Do a little harmless rercursion here _ClearState(ftp_passive); return _OpenDataConnection(); } for (i = 0; i < 6; i++) ucaddr[i] = (unsigned char)(paddr[i] & 0xff); memcpy(&sa.sin_addr, &ucaddr[0], (size_t) 4); memcpy(&sa.sin_port, &ucaddr[4], (size_t) 2); addr.SetTo(sa); if (fData->Connect(addr) == B_NO_ERROR) rc = true; } } } else { // cannot do passive. Do a little harmless rercursion here _ClearState(ftp_passive); rc = _OpenDataConnection(); } } else { // Here we bind to a local port and send a PORT command if (fData->Bind() == B_NO_ERROR) { char buf[255]; fData->Listen(); addr = fData->LocalAddr(); addr.GetAddr(buf, &port); host = buf; i = 0; while (i >= 0) { i = host.find('.', i); if (i >= 0) host[i] = ','; } sprintf(buf, ",%d,%d", (port & 0xff00) >> 8, port & 0x00ff); cmd = "PORT "; cmd += host; cmd += buf; _SendRequest(cmd); _GetReply(replyString, code, codeType); // PORT failure is in the 500-range if (codeType == 2) rc = true; } }