I am developing a bot for Skype in Java. Right now, I only want the bot to authenticate (get bearer token) and to echo received messages.
I did last test on 31st July 2017 and it worked fine. But, since August, the strangest thing is happening:
The bot can authenticate correctly, and I got the bearen token and its timeout. After that, the SslSocket starts listening. When I chat the bot, it gets a connection (initiates handshake and all that) but receives nothing. No headers, no payload, nothing.
I tried reading documentation and see if the latest update to Microsoft Bot Framework had anything to do with it, but I couldn't find anything.
Anyone can help me about what's going on?
InputStream inputStream = sslSocket.getInputStream();
OutputStream outputStream = sslSocket.getOutputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(outputStream));
String line = null;
String jsonLine = null;
String challenge = null;
while(((line = bufferedReader.readLine()) != null)){
System.out.println("iline = "+line);
if (!line.isEmpty()){
if(line.substring(0,1).equals("{")){
jsonLine = line;
}
}
}
This is the part of the code which reads the incoming message. JsonLine and line are always null.
Certificate was expired. Once renewed, everything started working again.
Related
I have code on an android (Xamarin) device as such:
socket = new Socket();
socket.Connect(new InetSocketAddress(IP_ADDR, PORT));
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.InputStream));
PrintWriter writer = new PrintWriter(socket.OutputStream, true);
string userInput = "";
while ((userInput = reader.ReadLine()) != null)
{
writer.Println(userInput);
}
The server side is a Windows server. I am reading data fine. But Println is never sending the data. I have tried .Flush() afterward, to no avail. I even considered possible newline differences and changed the code to just .Print() with 13 and 10 after, then a flush. Still nothing. Any thoughts? TIA
Moments later, I discovered the answer.
Instead of 13, 10, I send the char representation, ala:
writer.Print(userInput);
writer.Print('\r');
writer.Print('\n');
writer.Flush();
I'm trying to make a chat application between a server and clients which are seperate classes. I'm not copying the whole code, but this is the part I'm not sure is set up correctly:
Server:
ServerSocket s = null;
Socket c = null;
s = new ServerSocket(5002);
c = s.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(c.getInputStream()))
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(c.getOutputStream()));
out.flush();
String line;
line = in.readLine();
out.write("#W|Welcome");
line = in.readLine();
out.write("#W|Welcome");
line = in.readLine();
out.write("#W|Welcome");
Client :
Socket socket = new Socket("localhost", 5002);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream ()));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String line;
out.flush();
out.write("#J|test");
line = in.readLine();
out.write("#J|test");
line = in.readLine();
After the client does out.println(), the server's in.readLine() gets the line. But when it's the other way around, the client keeps waiting at in.readLine(). (I used the debugger and watched the server execute out.println() and go past it, while the client is still stuck at in.readLine().
Are my data streams set up correctly or is there probably an error in my code somewhere else? I'm not sure how to check in the debugger if the streams are connected correctly.
[Quoting my comment above:]
There is nothing here that [reads or] writes lines.
That remains true. All you have is:
out.write("#W|Welcome");
etc.
don't forget to call newLine() as necessary
You forgot.
I have android client and C++ server with working ssl (TLS) connection. But for every message I have to open new ssl session and so on.
Can I send multiple messages over one ssl socket? How?
I have tried reuse my one-message working code as below.
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(sslSocket.getOutputStream()));
w.write(request, 0, request.length());
w.flush(); // this works (server got data)
BufferedReader r = new BufferedReader(new InputStreamReader(sslSocket.getInputStream()));
StringBuilder response = new StringBuilder();
String actRecieved = null;
while ((actRecieved = r.readLine()) != null) {
response.append(actRecieved);
}
Log.d("TEST", "one: " + response.toString()); // this works (server send data, I read it)
request = "some special request 2";
w.write(request, 0, request.length());
w.flush(); // this does not work, no data went to server, but no error occured
actRecieved = null;
response = new StringBuilder();
while ((actRecieved = r.readLine()) != null) {
response.append(actRecieved);
}
Log.d("TEST", "two: " + response.toString()); // this does not work as well, because server is not send any data
So, where is the problem? Can anyone tell me?
Update
I have just found out that 2 write requests will reach the server when I don't read from stream.
Is there any problem with using input and output stream mutliple-times from one socket?
Should I use two sockets - one for read and one for write?
Help anybody.
Ok, finally I found solution on my own.
The problem was in reading, because r.readLine() blocked until server closed connection, so after this nothing could be sent.
Now client is not waiting for server to close connection, but it checks if the message is complete.
Like this:
while ((actRecieved = r.readLine()) != null) {
response.append(actRecieved);
if(actRecieved.endsWith("SomeEndMark")
break;
}
Hope this will help to someone else.
Today I started developing a new Android app which is based on the Windows Azure Mobile Services.
I've tried to use the SDK provided by Microsoft for the whole day, without any success. Every time the app performs a web request, this one returns a 400, BAD REQUEST code.
I go to a lower level, with the following code.
URL url = new URL("https://xxxx.azure-mobile.net/api/contents"); //host obscured
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setDoInput(true);
//I obscure the authentication and app key, but they are correct in the program
conn.addRequestProperty("AUTHORIZATION", "Basic xxxxxxxxxxxxxxx");
conn.addRequestProperty("X-ZUMO-APPLICATION", "xxxxxxxxxxxxxxxx");
conn.addRequestProperty("ACCEPT", "application/json");
//connect
conn.connect();
int code = conn.getResponseCode(); //400 in the emulator, 200 in a standard java code
String message = conn.getResponseMessage();
InputStream is = conn.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String read = null;
StringBuilder sb = new StringBuilder();
do {
//Read the content
read = br.readLine();
sb.append(read);
} while(read != null);
//print the content
System.out.println(sb.toString());
//Close the buffers
br.close();
isr.close();
is.close();
System.out.println("Status Code: "+code);
System.out.println(message);
conn.disconnect();
It works perfectly in a standard java application, but in the emulator I still get 400 BAD REQUEST. I really do not understand why!
Maybe an issue of the emulator?
I was running an Android Emulator with API 10.
I'd like to try the code on a real device, but the mac does not recognize it... And the device worked until yesterday since I debugged an application with it.
If you know what I am doing wrong, please help me.
EDIT 20-03-2014:
I made some other attempts. I tried with the HttpClient API. No luck.
I'm still getting 400 as response code and Bad Request as response Message.
The thrown Exception is UnknownHostException... But the InetAddress.getByName(); successfully get an IP address for my web service.
The app still work with Android version greater than 4, I have not tried with Android 3.
I'm very sad and frustrated...
Thank you for your time,
Rik.
SOLVED
Oddly, the problem was in the AUTHENTICATION header.
I computed the header with the following code:
public setHeader(String code, String username)
{
StringBuilder sb = new StringBuilder(username);
sb.append(":");
sb.append(code);
sb = new StringBuilder(Base64.encodeToString(sb.toString().getBytes(), Base64.DEFAULT));
sb.insert(0, "Basic ");
auth = sb.toString();
}
The Base64.encodeToString() method adds a \n at the end of the line. .__.
By adding a trim() in the last line, I threw away the new line and everything went fine in both 2.3.3 and 4 Android versions.
I am using Apache HTTPClient 4 to connect to twitter's streaming api with default level access. It works perfectly well in the beginning but after a few minutes of retrieving data it bails out with this error:
2012-03-28 16:17:00,040 DEBUG org.apache.http.impl.conn.SingleClientConnManager: Get connection for route HttpRoute[{tls}->http://myproxy:80->https://stream.twitter.com:443]
2012-03-28 16:17:00,040 WARN com.cloudera.flume.core.connector.DirectDriver: Exception in source: TestTwitterSource
java.lang.IllegalStateException: Invalid use of SingleClientConnManager: connection still allocated.
at org.apache.http.impl.conn.SingleClientConnManager.getConnection(SingleClientConnManager.java:216)
Make sure to release the connection before allocating another one.
at org.apache.http.impl.conn.SingleClientConnManager$1.getConnection(SingleClientConnManager.java:190)
I understand why I am facing this issue. I am trying to use this HttpClient in a flume cluster as a flume source. The code looks like this:
public Event next() throws IOException, InterruptedException {
try {
HttpHost target = new HttpHost("stream.twitter.com", 443, "https");
new BasicHttpContext();
HttpPost httpPost = new HttpPost("/1/statuses/filter.json");
StringEntity postEntity = new StringEntity("track=birthday",
"UTF-8");
postEntity.setContentType("application/x-www-form-urlencoded");
httpPost.setEntity(postEntity);
HttpResponse response = httpClient.execute(target, httpPost,
new BasicHttpContext());
BufferedReader reader = new BufferedReader(new InputStreamReader(
response.getEntity().getContent()));
String line = null;
StringBuffer buffer = new StringBuffer();
while ((line = reader.readLine()) != null) {
buffer.append(line);
if(buffer.length()>30000) break;
}
return new EventImpl(buffer.toString().getBytes());
} catch (IOException ie) {
throw ie;
}
}
I am trying to buffer 30,000 characters in the response stream to a StringBuffer and then return this as the data received. I am obviously not closing the connection - but I do not want to close it just yet I guess. Twitter's dev guide talks about this here It reads:
Some HTTP client libraries only return the response body after the
connection has been closed by the server. These clients will not work
for accessing the Streaming API. You must use an HTTP client that will
return response data incrementally. Most robust HTTP client libraries
will provide this functionality. The Apache HttpClient will handle
this use case, for example.
It clearly tells you that HttpClient will return response data incrementally. I've gone through the examples and tutorials, but I haven't found anything that comes close to doing this. If you guys have used a httpclient (if not apache) and read the streaming api of twitter incrementally, please let me know how you achieved this feat. Those who haven't, please feel free to contribute to answers. TIA.
UPDATE
I tried doing this: 1) I moved obtaining stream handle to the open method of the flume source. 2) Using a simple inpustream and reading data into a bytebuffer. So here is what the method body looks like now:
byte[] buffer = new byte[30000];
while (true) {
int count = instream.read(buffer);
if (count == -1)
continue;
else
break;
}
return new EventImpl(buffer);
This works to an extent - I get tweets, they are nicely being written to a destination. The problem is with the instream.read(buffer) return value. Even when there is no data on the stream, and the buffer has default \u0000 bytes and 30,000 of them, so this value is getting written to the destination. So the destination file looks like this.. " tweets..tweets..tweeets.. \u0000\u0000\u0000\u0000\u0000\u0000\u0000...tweets..tweets... ". I understand the count won't return a -1 coz this is a never ending stream, so how do I figure out if the buffer has new content from the read command?
The problem is that your code is leaking connections. Please make sure that no matter what you either close the content stream or abort the request.
InputStream instream = response.getEntity().getContent();
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(instream));
String line = null;
StringBuffer buffer = new StringBuffer();
while ((line = reader.readLine()) != null) {
buffer.append(line);
if (buffer.length()>30000) {
httpPost.abort();
// connection will not be re-used
break;
}
}
return new EventImpl(buffer.toString().getBytes());
} finally {
// if request is not aborted the connection can be re-used
try {
instream.close();
} catch (IOException ex) {
// log or ignore
}
}
It turns out that it was a flume issue. Flume is optimized to transfer events of size 32kb. Anything beyond 32kb, Flume bails out. (The workaround is to tune event size to be greater than 32KB). So, I've changed my code to buffer 20,000 characters at least. It kind of works, but it is not fool proof. This can still fail if the buffer length exceeds 32kb, however, it hasn't failed so far in an hour of testing - I believe it has to do with the fact that Twitter doesn't send a lot of data on its public stream.
while ((line = reader.readLine()) != null) {
buffer.append(line);
if(buffer.length()>20000) break;
}