Skip to content

Commit 40840db

Browse files
DSheirerDennis Sheirer
andauthored
#2062 Verbose logging option for Broadcastify Feed to troubleshoot streaming connection issues. (#2063)
Co-authored-by: Dennis Sheirer <[email protected]>
1 parent 786ae93 commit 40840db

File tree

3 files changed

+156
-38
lines changed

3 files changed

+156
-38
lines changed

src/main/java/io/github/dsheirer/audio/broadcast/broadcastify/BroadcastifyFeedConfiguration.java

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,20 @@
11
/*
2+
* *****************************************************************************
3+
* Copyright (C) 2014-2024 Dennis Sheirer
24
*
3-
* * ******************************************************************************
4-
* * Copyright (C) 2014-2020 Dennis Sheirer
5-
* *
6-
* * This program is free software: you can redistribute it and/or modify
7-
* * it under the terms of the GNU General Public License as published by
8-
* * the Free Software Foundation, either version 3 of the License, or
9-
* * (at your option) any later version.
10-
* *
11-
* * This program is distributed in the hope that it will be useful,
12-
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
13-
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14-
* * GNU General Public License for more details.
15-
* *
16-
* * You should have received a copy of the GNU General Public License
17-
* * along with this program. If not, see <http://www.gnu.org/licenses/>
18-
* * *****************************************************************************
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
199
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
2014
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>
17+
* ****************************************************************************
2118
*/
2219
package io.github.dsheirer.audio.broadcast.broadcastify;
2320

@@ -35,6 +32,7 @@ public class BroadcastifyFeedConfiguration extends IcecastTCPConfiguration
3532
private final static Logger mLog = LoggerFactory.getLogger(BroadcastifyFeedConfiguration.class);
3633

3734
private int mFeedID;
35+
private boolean mVerboseLogging = false;
3836

3937
public BroadcastifyFeedConfiguration()
4038
{
@@ -123,4 +121,15 @@ public void setFeedID(int feedID)
123121
{
124122
mFeedID = feedID;
125123
}
124+
125+
@JacksonXmlProperty(isAttribute = true, localName = "verbose_logging")
126+
public boolean isVerboseLogging()
127+
{
128+
return mVerboseLogging;
129+
}
130+
131+
public void setVerboseLogging(boolean verboseLogging)
132+
{
133+
mVerboseLogging = verboseLogging;
134+
}
126135
}

src/main/java/io/github/dsheirer/audio/broadcast/icecast/IcecastTCPAudioBroadcaster.java

Lines changed: 90 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* *****************************************************************************
3-
* Copyright (C) 2014-2022 Dennis Sheirer
3+
* Copyright (C) 2014-2024 Dennis Sheirer
44
*
55
* This program is free software: you can redistribute it and/or modify
66
* it under the terms of the GNU General Public License as published by
@@ -20,6 +20,7 @@
2020

2121
import io.github.dsheirer.alias.AliasModel;
2222
import io.github.dsheirer.audio.broadcast.BroadcastState;
23+
import io.github.dsheirer.audio.broadcast.broadcastify.BroadcastifyFeedConfiguration;
2324
import io.github.dsheirer.audio.broadcast.icecast.codec.IcecastCodecFactory;
2425
import io.github.dsheirer.audio.convert.InputAudioFormat;
2526
import io.github.dsheirer.audio.convert.MP3AudioConverter;
@@ -39,6 +40,8 @@
3940
import org.apache.mina.core.service.IoHandlerAdapter;
4041
import org.apache.mina.core.session.IoSession;
4142
import org.apache.mina.filter.codec.ProtocolCodecFilter;
43+
import org.apache.mina.filter.logging.LogLevel;
44+
import org.apache.mina.filter.logging.LoggingFilter;
4245
import org.apache.mina.transport.socket.nio.NioSocketConnector;
4346
import org.slf4j.Logger;
4447
import org.slf4j.LoggerFactory;
@@ -56,6 +59,7 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
5659
private IoSession mStreamingSession = null;
5760

5861
private long mLastConnectionAttempt = 0;
62+
private boolean mVerboseLogging = false;
5963
private AtomicBoolean mConnecting = new AtomicBoolean();
6064

6165
/**
@@ -73,6 +77,11 @@ public IcecastTCPAudioBroadcaster(IcecastTCPConfiguration configuration, InputAu
7377
MP3Setting mp3Setting, AliasModel aliasModel)
7478
{
7579
super(configuration, inputAudioFormat, mp3Setting, aliasModel);
80+
81+
if(configuration instanceof BroadcastifyFeedConfiguration broadcastify)
82+
{
83+
mVerboseLogging = broadcastify.isVerboseLogging();
84+
}
7685
}
7786

7887
/**
@@ -132,9 +141,12 @@ private boolean connect()
132141
mSocketConnector = new NioSocketConnector();
133142
mSocketConnector.getSessionConfig().setWriteTimeout(WRITE_TIMEOUT_SECONDS);
134143

135-
// LoggingFilter loggingFilter = new LoggingFilter(IcecastTCPAudioBroadcaster.class);
136-
// loggingFilter.setMessageSentLogLevel(LogLevel.NONE);
137-
// mSocketConnector.getFilterChain().addLast("logger", loggingFilter);
144+
if(mVerboseLogging)
145+
{
146+
LoggingFilter loggingFilter = new LoggingFilter(IcecastTCPAudioBroadcaster.class);
147+
loggingFilter.setMessageSentLogLevel(LogLevel.NONE);
148+
mSocketConnector.getFilterChain().addLast("logger", loggingFilter);
149+
}
138150

139151
mSocketConnector.getFilterChain().addLast("codec",
140152
new ProtocolCodecFilter(new IcecastCodecFactory()));
@@ -148,6 +160,10 @@ private boolean connect()
148160
@Override
149161
public void run()
150162
{
163+
if(mVerboseLogging)
164+
{
165+
mLog.info("Attempting connection ...");
166+
}
151167
setBroadcastState(BroadcastState.CONNECTING);
152168

153169
try
@@ -156,32 +172,65 @@ public void run()
156172
.connect(new InetSocketAddress(getBroadcastConfiguration().getHost(),
157173
getBroadcastConfiguration().getPort()));
158174

175+
if(mVerboseLogging)
176+
{
177+
mLog.info("Socket created - asynchronous connect requested - entering wait period");
178+
}
179+
159180
boolean connected = future.await(CONNECTION_ATTEMPT_TIMEOUT_MILLISECONDS, TimeUnit.MILLISECONDS);
160181

161182
if(connected)
162183
{
184+
if(mVerboseLogging)
185+
{
186+
mLog.info("Connected.");
187+
}
188+
163189
mStreamingSession = future.getSession();
164190
mConnecting.set(false);
165191
return;
166192
}
193+
else
194+
{
195+
if(mVerboseLogging)
196+
{
197+
mLog.info("Not Connected. Connection attempt timeout [" + CONNECTION_ATTEMPT_TIMEOUT_MILLISECONDS + "ms] exceeded");
198+
}
199+
}
167200
}
168201
catch(RuntimeIoException rioe)
169202
{
170203
if(rioe.getCause() instanceof SocketException)
171204
{
205+
if(mVerboseLogging)
206+
{
207+
mLog.info("Socket error. This usually indicates sdrtrunk can't reach the server " +
208+
"address over the current network connection. Setting state to " +
209+
"NETWORK UNAVAILABLE", rioe);
210+
}
172211
setBroadcastState(BroadcastState.NETWORK_UNAVAILABLE);
173212
mConnecting.set(false);
174213
return;
175214
}
176215
}
177216
catch(UnresolvedAddressException uae)
178217
{
218+
if(mVerboseLogging)
219+
{
220+
mLog.info("Unresolved Address error. This means the domain name services can't resolve " +
221+
"the server URL to an IP address. Setting state to NETWORK UNAVAILABLE", uae);
222+
}
223+
179224
setBroadcastState(BroadcastState.NETWORK_UNAVAILABLE);
180225
mConnecting.set(false);
181226
return;
182227
}
183228
catch(Exception e)
184229
{
230+
if(mVerboseLogging)
231+
{
232+
mLog.info("Unknown error. An error occurred while attempting to connect to the server.", e);
233+
}
185234
mLog.error("Error", e);
186235
//Disregard ... we'll disconnect and try again
187236
}
@@ -190,6 +239,11 @@ public void run()
190239
mLog.error("Throwable error caught", t);
191240
}
192241

242+
if(mVerboseLogging)
243+
{
244+
mLog.info("Starting disconnect sequence since an error occurred while trying to connect.");
245+
}
246+
193247
disconnect();
194248
mConnecting.set(false);
195249
}
@@ -209,6 +263,11 @@ public void disconnect()
209263
{
210264
if(connected() && mStreamingSession != null)
211265
{
266+
if(mVerboseLogging)
267+
{
268+
mLog.info("Routine disconnect requested from a connected state with a non-null streaming session");
269+
}
270+
212271
mStreamingSession.closeNow();
213272
}
214273
else
@@ -217,6 +276,12 @@ public void disconnect()
217276
//want to preserve the error state that got us here, so the user can see it.
218277
if(!getBroadcastState().isErrorState())
219278
{
279+
if(mVerboseLogging)
280+
{
281+
mLog.info("Disconnect requested - previous non-error state was [" + getBroadcastState() +
282+
"] - changing state to DISCONNECTED");
283+
}
284+
220285
setBroadcastState(BroadcastState.DISCONNECTED);
221286
}
222287

@@ -282,12 +347,23 @@ public void sessionOpened(IoSession session) throws Exception
282347
mInlineActive = false;
283348
}
284349

350+
if(mVerboseLogging)
351+
{
352+
mLog.info("Session opened. Sending: " + sb);
353+
}
354+
355+
285356
session.write(sb.toString());
286357
}
287358

288359
@Override
289360
public void sessionClosed(IoSession session) throws Exception
290361
{
362+
if(mVerboseLogging)
363+
{
364+
mLog.info("Session closed. Setting connecting flag to false.");
365+
}
366+
291367
mLastConnectionAttempt = System.currentTimeMillis();
292368

293369
//If there is already an error state, don't override it. Otherwise, set state to disconnected
@@ -311,15 +387,23 @@ public void exceptionCaught(IoSession session, Throwable cause) throws Exception
311387
mLog.error("[" + getStreamName() + "] Broadcast error", cause);
312388
}
313389

390+
if(mVerboseLogging)
391+
{
392+
mLog.info("Session error caught.", cause);
393+
}
394+
314395
disconnect();
315396
}
316397

317398
@Override
318399
public void messageReceived(IoSession session, Object object) throws Exception
319400
{
320-
if(object instanceof String)
401+
if(object instanceof String message)
321402
{
322-
String message = (String) object;
403+
if(mVerboseLogging)
404+
{
405+
mLog.info("Message Received [" + message + "]");
406+
}
323407

324408
if(message != null && !message.trim().isEmpty())
325409
{

0 commit comments

Comments
 (0)