Trying to do FTP with my router from an ESP8266 WiFi-board and using the Arduino-IDE, I keep getting the following error message:
331 Password required for anonymous.
My code looks like this:
if (client.connect(server, 21)) { // 21 = FTP server
Serial.println(F("Command connected FIRST TIME"));
} else {
Serial.println(F("Command connection failed FIRST TIME"));
}
eRcv();
Serial.println("OUTPUT BUFFER 1");
Serial.println(outBuf);
client.println(F("USER anonymous"));
eRcv();
Serial.println("OUTPUT BUFFER 2");
Serial.println(outBuf);
client.println(F("PASS anonymous"));
eRcv();
Serial.println("OUTPUT BUFFER 3");
Serial.println(outBuf);
client.println(F("SYST"));
eRcv();
Serial.println("OUTPUT BUFFER 4");
Serial.println(outBuf);
client.println(F("Type I"));
eRcv();
My log looks like that:
WiFi connected; IP address: 192.168.178.33
Command connected FIRST TIME
OUTPUT BUFFER 1
220 FRITZ!Box7490 FTP server ready.
OUTPUT BUFFER 2
331 Password required for anonymous.
As you can see, the error message I receive (i.e. err 331) happens already at cmd nr 2 (i.e. "PASS anonymous2).
The router is set to accept an anonymous FTP (that should not be the problem). The router, of course, is set to allow FTP.
I read something about a "passive mode" (client.println(F("PASV"));) but it seems to me that the "PASS anonymous" should go through independent of PASV-mode ore not. Is this correct ?
Are there any other suggestions of what to do here ?
Much appreciated!
P.S. For completion, the FTP-receive (delivering the "outBuf" from the example-code above) looks like this:
//-------------- FTP receive
byte eRcv() {
byte respCode;
byte thisByte;
long StartTimeoutTime = millis();
while (!client.available() && (millis() - StartTimeoutTime < 1000))
{ // wait for answer with 1 second timeout
delay(1);
}
if (millis() - StartTimeoutTime >= 1000)
{
efail();
return 0;
}
respCode = client.peek();
outCount = 0;
while (client.available()) {
thisByte = client.read();
//Serial.write(thisByte);
if (outCount < 127) {
outBuf[outCount] = thisByte;
outCount++;
outBuf[outCount] = 0;
}
}
if (respCode >= '4') {
efail();
return 0;
}
return 1;
} // eRcv()
Anonymous authentication with FTP still requires that you send a username and a password. Traditionally the username is anonymous and an email address is used as a password. Something like user#test.com works fine. Here is a link to RFC 959, File Transfer Protocol.
From here it looks like you might not be waiting long enough for the server to send the 220 message before you send the USER. After you connect, wait for the server to finish sending its welcome message. Then send your USER, wait for the 331, then send your PASS. The server might also be sending multiple strings for the first message. Try logging into the FTP server with the commandline client for your o/s and see exactly what it's sending you, and adjust your code for that.
Related
Ive incorporated multiple features i want in a microcontroller program (ESP32 Wroom32) and needed some advice on the best way to keep the program running and receive messages while it is running.
Current code:
//includes and declarations
setup()
{
//setup up wifi, server
}
main(){
WiFiClient client = server.available();
byte new_command[40];
if (client) // If client object is created, a connection is setup
{
Serial.println("New wifi Client.");
String currentLine = ""; //Used to print messages
while (client.connected())
{
recv_byte = client.read();
new_command = read_incoming(&recv_byte, client); //Returns received command and check for format. If invalid, returns a 0 array
if (new_command[0] != 0) //Checks if message is not zero, None of valid messages start with zero
{
execute_command(new_command);
//new_command is set to zero
}
}//end of while loop
}//end of if loop
}
The downside of this is that the ESP32 waits till the command is finished executing before it is ready to receive a new message. It is desired that the ESP32 receive commands and store them, and execute it at its own pace. I am planning to change the current code to receive a messages while the code is running as follows:
main()
{
WiFiClient client = server.available();
byte new_command[40];
int command_count = 0;
byte command_array[50][40];
if (command_count != 0)
{
execute_command(command_array[0]);
//Decrement command_count
//Shift all commands in command_array by 1 row above
//Set last executed command to zero
}
}//end of main loop
def message_interrupt(int recv_byte, WiFiClient& running_client)
{
If (running_client.connected())
{
recv_byte = running_client.read();
new_command = read_incoming(&recv_byte, running_client); //Returns received command and check for format. If invalid, returns a 0 array
//add new command to command_array after last command
//increment command_count
}
}
Which interrupt do I use to receive the message and update the command_array ? https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wifi.html Doesnt mention any receive/transmit events. I couldnt find any receive/transmit interrupt either or maybe I searched for the wrong term.
I have the below shell script (expect) where I am trying to send SMS. I have referred many stack overflow references and found out that ctrl-z maps to \x1a. However, even after appending it to the message and sending to the port or sending ctrl z separately to the port didn't help me. It timeouts later.
The script is written to send sms in pdu format. Irrespective of that, I believe, this is a generic issue to send ctrl-z to port. If you feel the script has some other errors, please share the solution for the same.
Also the length (34) mentioned below is the length of the (PDU_LENGTH -2)/2 as per the specification. This length doesn't include ctrl-z character.
at_command = "AT+CMGS=34\r"
message_content = "0011000C810056890......"
Script:
set PROMPT "0"
set timeout "$COMMAND_TIMEOUT"
send "$at_command"
expect {
"OK" { puts "Command Accepted\n"; }
"ERROR" { puts "Command Failed\n"; }
timeout { puts "Unable to connect to $HOSTIP at $HOSTPORT"; exit 1 }
"*>*" { set PROMPT "1"; }
}
if { "$PROMPT" == "1" } {
send "$message_content"
send "\x1a"
expect {
"OK" { puts "\nCommand accepted"; }
"ERROR" { puts "\nCommand failed"; }
"*>*" { puts "CTRL-Z dint reach UT. Error..."; }
"*" { puts "Unexpected return value received"; }
}
}
Am very sure the script sends $message_content" to port but exits immediately after sending "$message_content".
OUTPUT:
AT+CMGS=34
>
I did something like this in c# with an SMS-Gateway-Modul.
I had to switch to PDU-Mode first!
After that i had to transmit the expected PDU-Length and finally the PDU itself.
Every command has to be committed with can carriage return ASC[13] and the PDU had to be committed with an ASC[26] finally.
Here you can see a schematic(!) flow, how i did it in c#:
1) Create PDU and get length
int len;
var pdu = PDUGenerator.GetPdu(destination, message, "", out len);
2) Switch to PDUMode
SendToCom("AT+CMGF=0" + System.Convert.ToChar(13));
3) Announce message length
SendToCom("AT+CMGS=" + len + System.Convert.ToChar(13));
4) Send PDU and commit
SendToCom(pdu + System.Convert.ToChar(26));
I'm implementing a TCP/IP application on Windows 7 that loops around a socket recv() call. For small amount of data (< 5 MB) it works fine, but for large data (>20 MB), the recv fails in between.
Details: My app needs to communicate with HTTP server running , both running on same machine, in this scenerio, tcp app is sending heavy data to HTTP server
It gives error = 2, recv returns 0.
Error 2 means ENOENT, but what does it means?. Does anyone know what this is (in regards to a socket) and how I can get around this?
msgLen = recv(s,msg,BUFFER_SIZE,0);
if(msgLen > 0)
{
// do processing
}
else
{
printf("\n no data received .... msgLen=%d",msgLen);
printf("\n no data received .... errno=%d",errno);
}
Update Code as per comment
msgLen = recv(s,msg,BUFFER_SIZE,0);
if(msgLen > 0)
{
// do processing
}
else if(msgLen == 0)
{
printf("\n sender disconnected");
}
else
{
printf("\n no data received .... msgLen=%d",msgLen);
printf("\n no data received .... errno=%d",WSAGetLastError());
}
The error I get now is:
Firstly, recv = 0 many times, i.e. sender disconnected;
Finally, recv returns -1, and error = 10053.
My TCP/IP application is sending data to HTTP Server. The same works fine with small data, but the issue comes with large amount of data. Is HTTP server getting time out?
When recv() returns 0, it means the other party disconnected gracefully (assuming that your requested buffer size is not 0). recv() only provides an error code when it returns SOCKET_ERROR (-1). On Windows, you have to use WSAGetLastError() to get the error code, not errno, eg:
msgLen = recv(s,msg,BUFFER_SIZE,0);
if(msgLen > 0)
{
// do processing
}
else if (msgLen == 0)
{
printf("\n sender disconnected");
}
else
{
printf("\n no data received .... error=%d",WSAGetLastError());
}
Also keep in mind that if you are using a non-blocking socket, the error code may be WSAEWOULDBLOCK, which is not a fatal error. You can use select() to detect when the socket has data and then attempt the recv() again.
I'm trying to implement a simple FTP client using winsock. I'm having problems trying to download a file. Here's the code I'm using at the moment:
bool FTPHandler::downloadFile(const char * remoteFilePath, const char * filePath) {
if (!isConnected()) {
setErrorMsg("Not connected, imposible to upload file...");
return false;
}
if (usePasiveMode) {
this->pasivePort = makeConectionPasive();
if (this->pasivePort == -1) {
//error msg will be setted by makeConectionPasive()
return false;
}
} else {
setErrorMsg("Unable to upload file not in pasive mode :S");
return false;
}
char * fileName = new char[500];
getFileName(remoteFilePath,fileName);
// Default name and path := current directory and same name as remote.
if (filePath == NULL) {
filePath = fileName;
}
if (!setDirectory(remoteFilePath)) {
return false;
}
char msg[OTHER_BUF_SIZE];
char serverMsg[SERVER_BUF_SIZE];
sprintf(msg,"%s%s\n",RETR_MSG,fileName);
send(sock, msg, strlen(msg), 0);
SOCKET passSocket;
SOCKADDR_IN passServer;
passSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (passSocket == INVALID_SOCKET) {
WSACleanup();
sprintf(errorMsg,"Error trying to create socket (WSA error code: %d)",WSAGetLastError());
return false;
}
passServer.sin_family = PF_INET;
passServer.sin_port = htons(this->pasivePort);
passServer.sin_addr = *((struct in_addr *)gethostbyname(this->host)->h_addr);
memset(server.sin_zero,0,8);
int errorCode = connect(passSocket, (LPSOCKADDR) &passServer, sizeof(struct sockaddr));
int tries = 0;
while (errorCode == SOCKET_ERROR) {
tries++;
if (tries >= MAX_TRIES) {
closesocket(passSocket);
sprintf(errorMsg,"Error trying to create socket");
WSACleanup();
return false;
}
}
char * buffer = (char *) malloc(CHUNK_SIZE);
ofstream f(filePath);
Sleep(WAIT_TIME);
while (int readBytes = ***recv(passSocket, buffer, CHUNK_SIZE, 0)***>0) {
buffer[readBytes] = '\0';
f.write(buffer,readBytes);
}
f.close();
Sleep(WAIT_TIME);
recv(sock, serverMsg, OTHER_BUF_SIZE, 0);
if (!startWith(serverMsg, FILE_STATUS_OKEY_CODE)) {
sprintf(errorMsg,"Bad response: %s",serverMsg);
return false;
}
return true;
}
That last recv() returns 1 byte several times, and then the method ends and the file that should be around 1Kb is just 23 bytes.
Why isn't recv reading the hole file?
There are all kinds of logic holes and incorrect/missing error handling in this code. You really need to clean up this code in general.
You are passing the wrong sizeof() value to connect(), and not handling an error correctly if connect() fails (your retry loop is useless). You need to use sizeof(sockaddr_in) or sizeof(passServer) instead of sizeof(sockaddr). You are also not initializing passServer correctly.
You are not checking recv() for errors. And in the off-chance that recv() actually read CHUCK_SIZE number of bytes then you have a buffer overflow that will corrupt memory when you write the null byte into the buffer (which you do not need to do) because you are writing it past the boundaries of the buffer.
If connect() fails, or recv() fails with any error other than a server-side initiated disconnect, you are not telling the server to abort the transfer.
Once you tell the server to go into Passive mode, you need to connect to the IP/Port (not just the Port) that the server tells you, before you then send your RETR command.
Don't forget to send the server a TYPE command so it knows what format to send the file bytes in, such as TYPE A for ASCII text and TYPE I for binary data. If you try to transfer a file in the wrong format, you can corrupt the data. FTP's default TYPE is ASCII, not Binary.
And lastly, since you clearly do not seem to know how to program sockets effectively, I suggest you use the FTP portions of the WinInet library instead of WinSock directly, such as the FtpGetFile() function. Let WinInet handle the details of transferring FTP files for you.
I have a C++ pipe server app and a C# pipe client app communicating via Windows named pipe (duplex, message mode, wait/blocking in separate read thread).
It all works fine (both sending and receiving data via the pipe) until I try and write to the pipe from the client in response to a forms 'textchanged' event. When I do this, the client hangs on the pipe write call (or flush call if autoflush is off). Breaking into the server app reveals it's also waiting on the pipe ReadFile call and not returning.
I tried running the client write on another thread -- same result.
Suspect some sort of deadlock or race condition but can't see where... don't think I'm writing to the pipe simultaneously.
Update1: tried pipes in byte mode instead of message mode - same lockup.
Update2: Strangely, if (and only if) I pump lots of data from the server to the client, it cures the lockup!?
Server code:
DWORD ReadMsg(char* aBuff, int aBuffLen, int& aBytesRead)
{
DWORD byteCount;
if (ReadFile(mPipe, aBuff, aBuffLen, &byteCount, NULL))
{
aBytesRead = (int)byteCount;
aBuff[byteCount] = 0;
return ERROR_SUCCESS;
}
return GetLastError();
}
DWORD SendMsg(const char* aBuff, unsigned int aBuffLen)
{
DWORD byteCount;
if (WriteFile(mPipe, aBuff, aBuffLen, &byteCount, NULL))
{
return ERROR_SUCCESS;
}
mClientConnected = false;
return GetLastError();
}
DWORD CommsThread()
{
while (1)
{
std::string fullPipeName = std::string("\\\\.\\pipe\\") + mPipeName;
mPipe = CreateNamedPipeA(fullPipeName.c_str(),
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
KTxBuffSize, // output buffer size
KRxBuffSize, // input buffer size
5000, // client time-out ms
NULL); // no security attribute
if (mPipe == INVALID_HANDLE_VALUE)
return 1;
mClientConnected = ConnectNamedPipe(mPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
if (!mClientConnected)
return 1;
char rxBuff[KRxBuffSize+1];
DWORD error=0;
while (mClientConnected)
{
Sleep(1);
int bytesRead = 0;
error = ReadMsg(rxBuff, KRxBuffSize, bytesRead);
if (error == ERROR_SUCCESS)
{
rxBuff[bytesRead] = 0; // terminate string.
if (mMsgCallback && bytesRead>0)
mMsgCallback(rxBuff, bytesRead, mCallbackContext);
}
else
{
mClientConnected = false;
}
}
Close();
Sleep(1000);
}
return 0;
}
client code:
public void Start(string aPipeName)
{
mPipeName = aPipeName;
mPipeStream = new NamedPipeClientStream(".", mPipeName, PipeDirection.InOut, PipeOptions.None);
Console.Write("Attempting to connect to pipe...");
mPipeStream.Connect();
Console.WriteLine("Connected to pipe '{0}' ({1} server instances open)", mPipeName, mPipeStream.NumberOfServerInstances);
mPipeStream.ReadMode = PipeTransmissionMode.Message;
mPipeWriter = new StreamWriter(mPipeStream);
mPipeWriter.AutoFlush = true;
mReadThread = new Thread(new ThreadStart(ReadThread));
mReadThread.IsBackground = true;
mReadThread.Start();
if (mConnectionEventCallback != null)
{
mConnectionEventCallback(true);
}
}
private void ReadThread()
{
byte[] buffer = new byte[1024 * 400];
while (true)
{
int len = 0;
do
{
len += mPipeStream.Read(buffer, len, buffer.Length);
} while (len>0 && !mPipeStream.IsMessageComplete);
if (len==0)
{
OnPipeBroken();
return;
}
if (mMessageCallback != null)
{
mMessageCallback(buffer, len);
}
Thread.Sleep(1);
}
}
public void Write(string aMsg)
{
try
{
mPipeWriter.Write(aMsg);
mPipeWriter.Flush();
}
catch (Exception)
{
OnPipeBroken();
}
}
If you are using separate threads you will be unable to read from the pipe at the same time you write to it. For example, if you are doing a blocking read from the pipe then a subsequent blocking write (from a different thread) then the write call will wait/block until the read call has completed and in many cases if this is unexpected behavior your program will become deadlocked.
I have not tested overlapped I/O, but it MAY be able to resolve this issue. However, if you are determined to use synchronous calls then the following models below may help you to solve the problem.
Master/Slave
You could implement a master/slave model in which the client or the server is the master and the other end only responds which is generally what you will find the MSDN examples to be.
In some cases you may find this problematic in the event the slave periodically needs to send data to the master. You must either use an external signaling mechanism (outside of the pipe) or have the master periodically query/poll the slave or you can swap the roles where the client is the master and the server is the slave.
Writer/Reader
You could use a writer/reader model where you use two different pipes. However, you must associate those two pipes somehow if you have multiple clients since each pipe will have a different handle. You could do this by having the client send a unique identifier value on connection to each pipe which would then let the server associate the two pipes. This number could be the current system time or even a unique identifier that is global or local.
Threads
If you are determined to use the synchronous API you can use threads with the master/slave model if you do not want to be blocked while waiting for a message on the slave side. You will however want to lock the reader after it reads a message (or encounters the end of a series of message) then write the response (as the slave should) and finally unlock the reader. You can lock and unlock the reader using locking mechanisms that put the thread to sleep as these would be most efficient.
Security Problem With TCP
The loss going with TCP instead of named pipes is also the biggest possible problem. A TCP stream does not contain any security natively. So if security is a concern you will have to implement that and you have the possibility of creating a security hole since you would have to handle authentication yourself. The named pipe can provide security if you properly set the parameters. Also, to note again more clearly: security is no simple matter and generally you will want to use existing facilities that have been designed to provide it.
I think you may be running into problems with named pipes message mode. In this mode, each write to the kernel pipe handle constitutes a message. This doesn't necessarily correspond with what your application regards a Message to be, and a message may be bigger than your read buffer.
This means that your pipe reading code needs two loops, the inner reading until the current [named pipe] message has been completely received, and the outer looping until your [application level] message has been received.
Your C# client code does have a correct inner loop, reading again if IsMessageComplete is false:
do
{
len += mPipeStream.Read(buffer, len, buffer.Length);
} while (len>0 && !mPipeStream.IsMessageComplete);
Your C++ server code doesn't have such a loop - the equivalent at the Win32 API level is testing for the return code ERROR_MORE_DATA.
My guess is that somehow this is leading to the client waiting for the server to read on one pipe instance, whilst the server is waiting for the client to write on another pipe instance.
It seems to me that what you are trying to do will rather not work as expected.
Some time ago I was trying to do something that looked like your code and got similar results, the pipe just hanged
and it was difficult to establish what had gone wrong.
I would rather suggest to use client in very simple way:
CreateFile
Write request
Read answer
Close pipe.
If you want to have two way communication with clients which are also able to receive unrequested data from server you should
rather implement two servers. This was the workaround I used: here you can find sources.