FTP: 500 unknow command - c++

i try to do basic ftp client and I have got problem. I succesfully send user and password with correct response, bud then if I want to send others command, it send me back "500 unknown command" everytime..
What can I do wrong?
Code:
string message = "PWD";
message.append("\n");
cout << message;
if((send(mysocket,message.c_str(),message.size() + 1, 0 )) < 0){
cerr << "Error" << endl;
return -1;
}

There is no PWD command in FTP, its called CWD. See RFC959 for the FTP commands.

Related

Live555 RTSP server does not use UDP

I have a pretty basic live555 RTSP server and client to stream a h264 stream written in c++.
Here's the code I have for the client (adapted from testProgs/testRTSPClient.cpp, bundled with live555)
client->scheduler = BasicTaskScheduler::createNew();
client->env = BasicUsageEnvironment::createNew(*client->scheduler);
client->rtspClient = NULL;
RTSP_CLIENT::eventLoopWatchVariable = 0;
openURL(client, *client->env, string(string("rtsp://") + ip_address + ":" + to_string(BASE_RTSP_PORT + iris_id) + "/iris").c_str());
client->env->taskScheduler().doEventLoop(&RTSP_CLIENT::eventLoopWatchVariable);
void openURL(RTSP_CLIENT* client, UsageEnvironment& env, char const* rtspURL) {
// Begin by creating a "RTSPClient" object. Note that there is a separate "RTSPClient" object for each stream that we wish
// to receive (even if more than stream uses the same "rtsp://" URL).
while (!client->rtspClient) {
client->rtspClient = ourRTSPClient::createNew(env, rtspURL, RTSP_CLIENT_VERBOSITY_LEVEL, "main");
}
// Next, send a RTSP "DESCRIBE" command, to get a SDP description for the stream.
// Note that this command - like all RTSP commands - is sent asynchronously; we do not block, waiting for a response.
// Instead, the following function call returns immediately, and we handle the RTSP response later, from within the event loop:
client->rtspClient->sendDescribeCommand(continueAfterDESCRIBE);
}
void continueAfterDESCRIBE(RTSPClient* rtspClient, int resultCode, char* resultString) {
do {
UsageEnvironment& env = rtspClient->envir(); // alias
StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias
if (resultCode != 0) {
env << *rtspClient << "Failed to get a SDP description: " << resultString << "\n";
delete[] resultString;
break;
}
char* const sdpDescription = resultString;
env << *rtspClient << "Got a SDP description:\n" << sdpDescription << "\n";
// Create a media session object from this SDP description:
scs.session = MediaSession::createNew(env, sdpDescription);
delete[] sdpDescription; // because we don't need it anymore
if (scs.session == NULL) {
env << *rtspClient << "Failed to create a MediaSession object from the SDP description: " << env.getResultMsg() << "\n";
break;
} else if (!scs.session->hasSubsessions()) {
env << *rtspClient << "This session has no media subsessions (i.e., no \"m=\" lines)\n";
break;
}
// Then, create and set up our data source objects for the session. We do this by iterating over the session's 'subsessions',
// calling "MediaSubsession::initiate()", and then sending a RTSP "SETUP" command, on each one.
// (Each 'subsession' will have its own data source.)
scs.iter = new MediaSubsessionIterator(*scs.session);
setupNextSubsession(rtspClient);
return;
} while (0);
// An unrecoverable error occurred with this stream.
shutdownStream(rtspClient);
}
Here's the code I have for the server (adapted from testProgs/testOnDemandRTSPServer.cpp, bundled with live555)
rtsp_server->taskSchedular = BasicTaskScheduler::createNew();
rtsp_server->usageEnvironment = BasicUsageEnvironment::createNew(*rtsp_server->taskSchedular);
rtsp_server->rtspServer = RTSPServer::createNew(*rtsp_server->usageEnvironment, BASE_RTSP_PORT + iris_id, NULL);
rtsp_server->eventLoopWatchVariable = 0;
if(rtsp_server->rtspServer == NULL) {
*rtsp_server->usageEnvironment << "Failed to create rtsp server ::" << rtsp_server->usageEnvironment->getResultMsg() <<"\n";
return false;
}
rtsp_server->sms = ServerMediaSession::createNew(*rtsp_server->usageEnvironment, "iris", "iris", "stream");
rtsp_server->liveSubSession = H264LiveServerMediaSession::createNew(*rtsp_server->usageEnvironment, true);
rtsp_server->sms->addSubsession(rtsp_server->liveSubSession);
rtsp_server->rtspServer->addServerMediaSession(rtsp_server->sms);
rtsp_server->taskSchedular->doEventLoop(&rtsp_server->eventLoopWatchVariable);
I was under the assumption that live555 by default used UDP to transport data to the client from the server, which is what I wanted for it's latency benefits over TCP. However while running the server client I happened to check netstat and I found this:
~# netstat | grep 8554
tcp 0 0 x.x.x.x:8554 wsip-x-x-x-x:39224 ESTABLISHED
It is however showing that the communications are going through TCP not UDP. I am a bit confused here, am I mis-interpreting netstat here?
Is there anything I need to tune in my c++ code to force the communication to go through UDP not TCP?
Okay so I figured out the answer. To help anyone else who is curious about this, the code is actually all correct. There is also no mis-interpretation of netstat. RTSP does indeed run over TCP not UDP. However the transport method of the A/V data runs on RTP, a connection that RTSP simply negotiates and instantiates. RTP almost always will run over UDP. To figure out what port and protocol the A/V data stream is going over you will need to sniff the packets sent out via RTSP. In my case the A/V data stream was indeed still going over UDP.

Issue connecting to IRC Server

Been working on creating an IRC bot recently, and while it seems to connect & work with most IRC servers, it seems to have issues with the Twitch IRC server (irc.twitch.tv).
When connecting to another server, data is received & sent without any issues, however with the twitch connection, I can't send or receive data.
Initialize:
Connection::Connection(char* server, int port, std::string nick, std::string pass)
{
fServer = server;
fPort = port;
fNick = nick;
fPass = pass;
fChanCount = 0;
clear_buffer();
fSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
cout << "Attempting to resolve host: " << fServer << endl;
fHost = resolve_host(fServer);
fSaddr.sin_addr.S_un.S_addr = fHost;
fSaddr.sin_port = htons(fPort);
fSaddr.sin_family = AF_INET;
cout << "Resolved to: " << fHost << endl;
}
Open Connection:
int Connection::Connect()
{
if (connect(fSock, (sockaddr*)&fSaddr, sizeof(fSaddr)) == SOCKET_ERROR)
{
cout << "Can't connect to " << fServer << endl;
return 0;
}
recv(fSock, fBuffer, 1024 * 8, 0);
cout << fBuffer << endl << endl << flush;
send_message("PASS " + fPass);
send_message("NICK " + fNick);
send_message("USER " + fNick + " 0 * :" + fNick);
return 1;
}
Clear Buffer:
void Connection::clear_buffer()
{
memset(fBuffer, 0, sizeof(fBuffer));
}
Receive:
string Connection::receive_message()
{
clear_buffer();
recv(fSock, fBuffer, 1024 * 8, 0);
return fBuffer;
}
Completely stumped on what could be causing this, can provide more detail if needed.
Your USER message does not look like what the RFC2812 spec is asking for.
3.1.3 User message
Command: USER
Parameters: <user> <mode> <unused> <realname>
The USER command is used at the beginning of connection to specify
the username, hostname and realname of a new user.
The <mode> parameter should be a numeric, and can be used to
automatically set user modes when registering with the server. This
parameter is a bitmask, with only 2 bits having any signification: if
the bit 2 is set, the user mode 'w' will be set and if the bit 3 is
set, the user mode 'i' will be set. (See Section 3.1.5 "User
Modes").
The <realname> may contain space characters.
Numeric Replies:
ERR_NEEDMOREPARAMS ERR_ALREADYREGISTRED
Example:
USER guest 0 * :Ronnie Reagan ; User registering themselves with a
username of "guest" and real name
"Ronnie Reagan".
USER guest 8 * :Ronnie Reagan ; User registering themselves with a
username of "guest" and real name
"Ronnie Reagan", and asking to be set
invisible.
Perhaps that's what is causing the problem?
Otherwise I have found some servers require a password in the PASS message even if the server is not configured to require one. In those cases I send:
PASS none

Network Programming Issue - buffer will only send once to the server

I am trying to send a file to a server using socket programming. My server and client are able to connect to each other successfully however I am expecting the while loop below to go through the entire file and add it to the server. The issue I am having is that it only send the first chunk and not the rest.
On the client side I have the following:
memset(szbuffer, 0, sizeof(szbuffer)); //Initialize the buffer to zero
int file_block_size;
while ((file_block_size = fread(szbuffer, sizeof(char), 256, file)) > 0){
if (send(s, szbuffer, file_block_size, 0) < 0){
throw "Error: failed to send file";
exit(1);
} //Loop while there is still contents in the file
memset(szbuffer, 0, sizeof(szbuffer)); //Reset the buffer to zero
}
On the server side I have the following:
while (1)
{
FD_SET(s, &readfds); //always check the listener
if (!(outfds = select(infds, &readfds, NULL, NULL, tp))) {}
else if (outfds == SOCKET_ERROR) throw "failure in Select";
else if (FD_ISSET(s, &readfds)) cout << "got a connection request" << endl;
//Found a connection request, try to accept.
if ((s1 = accept(s, &ca.generic, &calen)) == INVALID_SOCKET)
throw "Couldn't accept connection\n";
//Connection request accepted.
cout << "accepted connection from " << inet_ntoa(ca.ca_in.sin_addr) << ":"
<< hex << htons(ca.ca_in.sin_port) << endl;
//Fill in szbuffer from accepted request.
while (szbuffer > 0){
if ((ibytesrecv = recv(s1, szbuffer, 256, 0)) == SOCKET_ERROR)
throw "Receive error in server program\n";
//Print reciept of successful message.
cout << "This is the message from client: " << szbuffer << endl;
File.open("test.txt", ofstream::out | ofstream::app);
File << szbuffer;
File.close();
//Send to Client the received message (echo it back).
ibufferlen = strlen(szbuffer);
if ((ibytessent = send(s1, szbuffer, ibufferlen, 0)) == SOCKET_ERROR)
throw "error in send in server program\n";
else cout << "Echo message:" << szbuffer << endl;
}
}//wait loop
} //try loop
The code above is the setup for the connection between the client and server which works great. It is in a constant while loop waiting to receive new requests. The issue is with my buffer. Once I send the first buffer over, the next one doesn't seem to go through. Does anyone know what I can do to set the server to receive more than just one buffer? I've tried a while loop but did not get any luck.
Your code that sends the file from the server appears to send consecutive sections of the file correctly.
Your code that appears to have the intention of receiving the file from the client performs the following steps:
1) Wait for and accept a socket.
2) Read up to 256 bytes from the socket.
3) Write those bytes back to the socket.
At this point the code appears to go back to waiting for another connection, and keeping the original connection open, and, at least based on the code you posted, obviously leaking the file descriptor.
So, the issues seems to be that the client and the server disagreeing on what should happen. The client tries to send the entire file, and doesn't read from the socket. The server reads the first 256 bytes from the socket, and writes it back to the client.
Of course, its entirely possible that portions of the code not shown implement some of the missing pieces, but there's definitely a disconnect here between what the sending side is doing, and what the receiving side is doing.
buffer will only send once to the server
No, your server is only reading once from the client. You have to loop, just like the sending loop does.

FTP server file transfer

I am uncertain about a few things regarding ftp file transfer. I am writing an ftp server and I am trying to figure out how to make the file tranfer work correctly. So far it works somehow but I have certain doubts. Here is my file transfer function (only retrieve so far):
void RETRCommand(int & clie_sock, int & c_data_sock, char buffer[]){
ifstream file; //clie_sock is used for commands and c_data_sock for data transfer
char *file_name, packet[PACKET_SIZE]; //packet size is 2040
int packet_len, pre_pos = 0, file_end;
file_name = new char[strlen(buffer + 5)];
strcpy(file_name, buffer + 5);
sprintf(buffer, "150 Opening BINARY mode data connection for file transfer\r\n");
if (send(clie_sock, buffer, strlen(buffer), 0) == -1) {
perror("Error while writing ");
close(clie_sock);
exit(1);
}
cout << "sent: " << buffer << endl;
file_name[strlen(file_name) - 2] = '\0';
file.open(file_name, ios::in | ios::binary);
if (file.is_open()) {
file.seekg(0, file.end);
file_end = (int) file.tellg();
file.seekg(0, file.beg);
while(file.good()){
pre_pos = file.tellg();
file.read(packet, PACKET_SIZE);
if ((int) file.tellg() == -1)
packet_len = file_end - pre_pos;
else
packet_len = PACKET_SIZE;
if (send(c_data_sock, packet, packet_len, 0) == -1) {
perror("Error while writing ");
close(clie_sock);
exit(1);
}
cout << "sent some data" << endl;
}
}
else {
sprintf(buffer, "550 Requested action not taken. File unavailable\r\n", packet);
if (send(clie_sock, buffer, packet_len + 2, 0) == -1) {
perror("Error while writing ");
close(clie_sock);
exit(1);
}
cout << "sent: " << buffer << endl;
delete(file_name);
return;
}
sprintf(buffer, "226 Transfer complete\r\n");
if (send(clie_sock, buffer, strlen(buffer), 0) == -1) {
perror("Error while writing ");
close(clie_sock);
exit(1);
}
cout << "sent: " << buffer << endl;
close(c_data_sock);
delete(file_name);
}
So one problem is the data transfer itself. I am not exactly sure how it is supposed to work. Now it works like this: the server sends all the data to c_data_sock, closes this socket and then the client starts doing something. Shouldn't the client recieve the data while the server is sending them? And the other problem is the abor command. How am I supposed to recieve the abor command? I tried recv with flag set to MSG_OOB but then I get an error saying "Invalid argument". I would be glad if someone could give me a hint or an example of how to do it right as I don't seem to be able to figure it out myself.
Thanks,
John
Ftp use two connections. First - is command connection, in your case it is clie_sock. 'ABOR' command should be received though it. You going to receive it the same way you received 'RETR' command.
To receive file client establishes data connection with your server ( c_data_sock socket ). It will not be opened till client connects, so this is the answer to your second question. You cannot start client after server executes this function. First client sends 'retr' command to your command socket. Then your sever waits new connection from client ( after sending him data ip and port ). Then client connects ( now you have your c_data_sock ready ) and sends all the data to that socket, which are in turn received by the client.
You probably need to read more about networking in general if you feel you don't understand it. I prefer this one: http://beej.us/guide/bgnet/
Also you have a memory leak here, after you allocate an array with the
file_name = new char[strlen(buffer + 5)];
you need to delete it using
delete [] file_name;
Otherwise file_name will be treated as a simple pointer, not an array, so most of array memory will be kept by your application which is bad especially when creating server.

How to make a synchronous chat program to send and receive messages synchronously?

At the moment I am creating a client server console application in c++. With the use of the winsock2.h library and UDP protocol we use the sendto and recvfrom to send messages as strings from the client to the server which will then send the message to a different client, right now if the client1 sends a message to client2, client2 will not receive the message until they attempt to send a message to client1. I am looking to make the program work like an instant messenger, so that when client1 sends a message to client2, client2 will receive it almost instantly without having to send a message first.
Also if client1 were to send a message to client2, client1 would not be able to send another message unless client2 had replied to the first one.
If you need more information or to see some code just ask.
The send code:
while( getline( cin, line ) )
{
// send a string to the server.
sendto( hSocket, line.c_str(), line.size(), 0,
reinterpret_cast<sockaddr*>( &serverAddress ),
sizeof( serverAddress ) );
// recieve the response.
int n = recvfrom( hSocket, recvLine, MAXLINE, 0, NULL, NULL );
if( n == -1 )
{
cout << "no reply" << endl;
}
else
{
recvLine[n] = 0;
string const terminateMsg = "server exit";
string msg = recvLine;
if( msg == terminateMsg )
{
cout << "Server terminated" << endl;
break;
}
cout << n << ": " << recvLine << endl;
}
}
right now if the client1 sends a message to client2, client2 will not
receive the message until they attempt to send a message to client1.
you've coded it that way.
Also if client1 were to send a message to client2, client1 would not
be able to send another message unless client2 had replied to the
first one.
Again, you've coded it that way. Your code assumes every sendto() is followed by a recvfrom(). But your question indicates that isn't what you want. I added some comments to your code below
while( getline( cin, line ) )
{
// send a string to the server. <-- will never get here a 2nd time through the loop without recvfrom() returning
sendto( hSocket, line.c_str(), line.size(), 0,
reinterpret_cast<sockaddr*>( &serverAddress ),
sizeof( serverAddress ) );
// recieve the response. <--- will never get here without getline() returning
int n = recvfrom( hSocket, recvLine, MAXLINE, 0, NULL, NULL );
if( n == -1 )
{
cout << "no reply" << endl;
}
else
{
recvLine[n] = 0;
string const terminateMsg = "server exit";
string msg = recvLine;
if( msg == terminateMsg )
{
cout << "Server terminated" << endl;
break;
}
cout << n << ": " << recvLine << endl;
}
}
I am looking to make the program work like an instant messenger, so
that when client1 sends a message to client2, client2 will receive it
almost instantly without having to send a message first.
Use Boost.Asio and asynchronous sockets, the async chat_client example does this very thing perfectly using TCP sockets, it is fairly trivial to modify the example for UDP. The async UDP echo server example may be useful as well. You'll want to use boost::asio::ip::udp::socket::async_recv_from() and boost::asio::ip::udp::socket::async_send_to(). The other BSD socket interfaces have equivalent mappings described in the documentation.