Professional Documents
Culture Documents
Walkie-Talkie
INTERNSHIP REPORT ON
Training Program
at
Plug
Submitted by
Vipin Bohra
19CS8100
Professor
India
April 2023
West Bengal
India
BONA-FIDE CERTIFICATE
It is certified that the work contained in the Project entitled "Plug App online walkie talkie" has
been carried out by “Vipin Bohra (Roll No. 19CS8100)” under the supervision of Mr. Manish
Singh Bisht, the data reported here in is original and that this work has not been submitted
elsewhere for any other Degree or Diploma.
Vipin Bohra
Date: 30/04/2023
This is to certify that the above declaration is true.
Introduction
Abstract
Contents
Title Page i
Bona-fide certificate ii
Introduction iii
Abstract iv
Table of Contents v
Callbacks are functions that are passed as arguments to other functions and are executed when a
certain task is completed. Callbacks are commonly used for asynchronous tasks such as reading
data from a file, making an HTTP request, or executing a database query.
Promises are objects that represent the eventual completion or failure of an asynchronous
operation and allow you to handle the result or error of that operation asynchronously. Promises
are commonly used for tasks that return a single value such as making an HTTP request or
executing a database query.
Async/await is a newer syntax that simplifies asynchronous programming by allowing you to
write asynchronous code that looks and behaves like synchronous code. Async/await uses
promises under the hood and allows you to write asynchronous code that is easier to read and
maintain.
Modules in JavaScript are a way to organize code into separate files, making it easier to manage
and reuse code across multiple files and applications. Modules allow you to encapsulate code
into logical units and expose only the necessary parts of that code to other modules.
In JavaScript, modules can be created using the CommonJS module system or the ECMAScript
module system.
The CommonJS module system is used in Node.js and allows you to use the module.exports
object to export a module's functionality. You can then use the require () function to import that
functionality into other modules.
The ECMAScript module system is used in modern browsers and allows you to use the export
keyword to export a module's functionality and the import keyword to import that functionality
into other modules
1.2 React
React is a popular JavaScript library for building user interfaces. It was developed by Facebook
and is now maintained by a large community of developers.
React allows you to build reusable UI components that can be composed together to create
complex and dynamic user interfaces. React uses a declarative programming model, which
means that you describe what you want your UI to look like and react takes care of the
underlying logic to make it happen.
React uses a virtual DOM (Document Object Model) to efficiently update the user interface.
When data changes, react calculates the minimal number of changes needed to update the virtual
DOM and then updates the real DOM accordingly. This makes React highly performant and
efficient. React can be used to build web applications, mobile applications, and even desktop
applications using tools like Electron.
React is often used in conjunction with other technologies like React Router for client-side
routing, Redux for state management, and Axios for making HTTP requests. React also has a
large ecosystem of third-party libraries and plugins that can help you accomplish almost any
task.
Overall, react is a powerful and flexible library for building user interfaces and has become a popular choice
for front-end developers due to its performance, scalability, and ease of use.
i) JSX is a syntax extension for JavaScript that allows you to write HTML-like syntax in your
JavaScript code. JSX is used extensively in React to define UI components in a more intuitive
and readable way. JSX is not valid JavaScript, so it needs to be transpiled into regular JavaScript
using a tool like Babel before it can be executed in a browser or Node.js environment.
ii) A React component is a self-contained piece of code that represents a reusable piece of UI. A
component can be as simple as a button or as complex as an entire application. Components can
be thought of as building blocks for your UI and can be composed together to create more
complex user interfaces. Components in React can be either functional or class-based, but both
types can be used to create reusable UI elements.
iii) State and props are two important concepts in React components. State is used to manage the
internal state of a component, such as data that changes over time or user input. State can only be
modified using the setState() method and is private to the component. Props, on the other hand,
are used to pass data from a parent component to a child component. Props are read-only and
cannot be modified by the child component.
i)
React hooks are a feature introduced in React 16.8 that allow developers to use state and other
React features in functional components. Prior to hooks, state and lifecycle methods were only
available in class components.
i) The useState hook is used to manage states within a functional component. It takes an
initial state value and returns an array with two elements: the current state value and a
function to update the state value.
ii) The useEffect hook allows developers to perform side effects, such as fetching data from
an API or updating the DOM, in response to changes in the component's state or props.
iii) The useContext hook enables developers to share state between components without
passing props down through multiple levels of the component tree.
iv) The useRef hook allows developers to create a mutable reference to an element or value
that persists between re-renders of the component.
1.2.4 how react works Virtual Dom behind the scenes and component lifecycle.
1.2.5 controlled and uncontrolled component, react Events and react context.
Chapter 2
2.1 Login Page: created Button Component and login Component. The design is shown in fig.1.
2.2 Home Page: created different components like nav bar, group, user List, user status etc. The design
is shown in fig.2.
2.3 new group: this component is used to make new group. The design is shown in fig.3.
2.4 Chat Box: this component is used for showing previous chats and sending new messages. The design
is shown in fig.4.
Chapter 3
Firebase is a backend cloud computing service and application development platform provided
by Google
Firebase also provided a method to authenticate using firebase custom token provided by the
firebase admin server.]
Firebase also provides onAuthStateChanged listener to listen for any new user login or logout.
For logout we can call the sign-out function that will logout the user.
This database also provides security rules to determine who has read and written access to your
database, how your data is structured, and what indexes exist.
Firebase Realtime database provided get, set methods to fetch and add data on database and
onValue listener to listen the Realtime change on the database.
3.3 firebase storage.
Cloud Storage for Firebase provides a way to upload and share user generated content, such as
images and video, which allows us to build rich media content into our apps. Data is stored in a
Google Cloud Storage bucket — an exabyte scale object storage solution with high availability
and global redundancy. Cloud Storage for Firebase lets us securely upload these files directly
from mobile devices and web browsers, handling spotty networks with ease.
3.4 My Learning.
i) For app or webapp development that requires the login of user, for this feature firebase
authentication becomes a good choice because it can be used across all platforms may be the
apple, android or browser.
ii) firebase also provides other services like Realtime storage in database and storing the media
content such as images, audio and video etc. Hence using firebase cloud services makes sense for
faster development and cross platform apps.
Chapter 4
We have used different providers for sign in using firebase authentication. Fig.5. shows two
provider method.
Chapter 5
5.1 socket-client.io
5.1.1 Introduction
Socket.IO is a popular JavaScript library that enables real-time, bidirectional and event-based
communication between the browser and the server. It's commonly used in web applications that
require real-time updates, such as chat applications, online games, and collaboration tools.
The "socket.io-client" library provides a client-side API for connecting to a Socket.IO server
from a web browser or a mobile app. It enables real-time data exchange, such as chat messages,
notifications, and updates, between the client and server.
i) Client connects to the server: When a client wants to connect to the server, it sends a
WebSocket handshake request. If WebSocket is not available, it can use other fallback
options such as long-polling, which means it sends a request to the server and waits for
the server to respond before sending the next request.
ii) Server and client establish a connection: Once the handshake is successful, a connection
between the client and the server is established. The connection remains open until it is
closed by either the client or the server.
iii) Events are exchanged: With the connection established, the client and server can now
exchange events. An event is a message sent by either the client or server that contains a
payload of data. When an event is received, the recipient can choose to respond with
another event.
iv) Rooms and namespaces: Socket.IO allow clients to join rooms or namespaces, which can
be used to group clients together and send targeted events to specific clients or groups of
clients.
v) Disconnection handling: Socket.IO can detect when a client has disconnected from the
server, whether it was intentional or due to network issues. The server can then choose to
notify other clients in the same room or namespace about the disconnection.
5.1.2 Events
In Socket.IO, events are messages that are exchanged between the server and the client. Events
are a way of passing data between the two, and they can be used to trigger actions on either the
server or the client.
Socket.IO provides a simple API for creating and handling events. The API includes two
methods: emit () and on (). The emit () method is used to send an event from the client to the
server, while the on () method is used to listen for events on the server or the client.
Socket.IO also provides a few built-in events, such as 'connect', 'disconnect', and 'error', which
can be used to handle connections, disconnections, and errors.
5.1.3 My learning
i) We use socket.io for full-duplex communication and it also reliable because of http long-
pooling while fallback
ii) The WebSocket protocol enables interaction between a web browser (or other client
application) and a web server with lower overhead than half-duplex alternatives such as
HTTP polling, facilitating real-time data transfer from and to the server.
iii) Since socket.io is based on event-based communication. So, client or server can emit any
event and adding the on listener for that event on other side will listen to that event and
get the payload sent with that event. This approach will work best for real-time
communication like sending messages to all the connected users in a socket room.
Broadcasting the message on groups chat room.
iv) Some custom events are also present that will emit after certain thing happened in socket
connection like connect event will be emit when client and server both will be connected
successfully through web socket.
While connecting to server socket we are also sending user token which we get after firebase
authentication. For checking if a valid user who already has account is connecting to socket or
using our backend API.
Same way we subscribe for type “user” for getting all user list with their online status. And
sending the “makeRequest” for set user online or set user offline. We can also listen to new
online or offline users.
Subscribing to signals will let us get to all groups where line is on (someone is talking in that
group) and signal busy for the user mean who is busy on other call. We are also listening to
“lineOn”, “lineOff” and “busy_signal” to get to know who is talking in which group.
Chapter 6
6.1 Redux
6.1.1 Introduction
Redux is a predictable state container for JavaScript applications. It is commonly used with
libraries like React for building user interfaces. Redux provides a centralized store that holds the
state of an application and provides a predictable way to update that state.
In a Redux application, the state is stored as a single object tree inside a Redux store. The only
way to modify the state is by dispatching an action, which is a plain JavaScript object that
describes the change that needs to be made to the state. Reducers are functions that take the
current state and an action, and return a new state based on the action.
One of the main benefits of using Redux is that it helps manage the complexity of state in large
applications. By keeping the state in a centralized location and enforcing a strict unidirectional
data flow, Redux makes it easier to reason about an application's behavior and debug issues.
Additionally, Redux allows for easy integration with other tools like middleware and time-travel
debugging.
i) Store: The store is a JavaScript object that holds the state of an application. It is the single
source of truth for the entire application's state. The store is created by passing a reducer
function to the Redux createStore function. The store has three important methods:
getState, dispatch, and subscribe.
ii) Actions: Actions are plain JavaScript objects that describe a change to the state. An
action must have a type property, which is a string that describes the type of the action.
Other properties of the action can contain additional data needed to update the state.
Actions are typically created by action creator functions, which are functions that return
an action object. Once an action is created, it is dispatched to the store using the store's
dispatch method.
iii) Reducers: Reducers are pure functions that take the current state and an action and return
a new state. A reducer must always return a new state object and must not modify the
current state directly. Reducers are passed as the first argument to the createStore
function and are called automatically by the store whenever an action is dispatched.
Reducers are responsible for updating the state in response to actions and should be
written to be as pure as possible.
6.1.3 My learning
(i) Concepts of Redux: The core concepts of Redux are store, actions, and reducers. The
store is a JavaScript object that holds the state of an application, and the only way to
modify the state is by dispatching an action. Actions are plain JavaScript objects that
describe a change to the state, and reducers are pure functions that take the current state
and an action and return a new state.
(ii) Implementing Redux: To implement Redux in a JavaScript application, I needed to
follow a few steps. First, I created a store by passing a reducer function to the Redux
createStore function. Then, I defined actions and action creators, which are functions that
return action objects. Finally, I defined reducers that specify how the state should change
in response to actions.
(iii) Benefits of using Redux: The benefits of using Redux include better code organization,
easier debugging, and a more predictable data flow. With Redux, I can more easily
reason about my application's behavior and debug issues. Additionally, Redux allows for
easy integration with other tools like middleware and time-travel debugging.
(iv) Common Redux tools: There are many tools available that work well with Redux.
Middleware can be used to modify the behavior of dispatching actions, while the Redux
DevTools allow for time-travel debugging and state visualization. These tools can help
me better understand how my application is behaving and make it easier to identify and
resolve issues.
The key benefit of using Redux Thunk is that it allows you to write action creators that have
more complex behavior, such as making an API call and then dispatching an action to update the
store with the result of the call. Without Redux Thunk, action creators can only return a plain
object, which limits their usefulness for more complex scenarios.
Redux Thunk works by intercepting actions that are dispatched to the store. If an action creator
returns a function instead of an object, Redux Thunk will call that function with dispatch and
getState arguments, which can be used to dispatch actions and access the current state of the
store. The function can then perform asynchronous operations and dispatch regular synchronous
actions to update the store.
Overall, Redux Thunk is a powerful tool that can make it easier to handle asynchronous
operations in your Redux application. By allowing you to write action creators that return
functions, you can more easily manage complex state updates based on the results of
asynchronous operations.
6.2.2 my learning
i) Concepts of Redux Thunk: The key concept of Redux Thunk is the ability to write
action creators that return functions instead of plain objects. These functions are called
thunks and can perform any kind of asynchronous operation. Thunks are typically used to
fetch data from an API or perform other side effects that can't be done synchronously.
Once the asynchronous operation is complete, the thunk can dispatch regular
synchronous actions to update the store.
ii) Using Redux Thunk: To use Redux Thunk in a JavaScript application, I needed to
install the redux-thunk package and add it to my Redux middleware stack. Once
installed, I could write action creators that return functions instead of plain objects. These
functions can use the dispatch and getState functions that are passed as arguments to
perform asynchronous operations and dispatch regular synchronous actions.
iii) Benefits of using Redux Thunk: The benefits of using Redux Thunk include the ability
to handle asynchronous operations more easily, improved code organization, and a more
predictable data flow. With Redux Thunk, I can write action creators that perform
complex asynchronous operations without making my code harder to reason about.
Additionally, Redux Thunk integrates well with other Redux tools and best practices,
such as using Redux Toolkit to further simplify state management.
Chapter 7
7.1 Normalization
Normalization is the process of restructuring your Redux store to optimize performance and
simplify state management. Normalization involves breaking down complex nested data
structures into simpler and more manageable pieces. This is important because large, nested state
structures can be difficult to work with and update efficiently. Normalizing data can make it
easier to perform efficient updates to the store and avoid unnecessary re-renders of components.
So based on the different components need different state to be re-render on state change we
have normalized our data structure as much as possible to remove unnecessary re-render.
Ex: - while subscribing to the user we will get the list of users who the member of my
organization with their online statue and total online time. Hence the online status and online
time are needed in different components. So, storing online status and online time in one data
structure here (map) makes no sense because it can cause unnecessary re-rendering. Hence, we
have normalized our data and stored online status and online time in different data structure
To connect component with the state we should not add the whole map data structure for every
component. We should connect component with only that key which is responsible for re-
rendering.
Ex: - user online status is a map data structure in the store, where key is the uid from firebase
now that map I am using in group component to show the green dot highlighting user is online.
So, if any user comes online, only the necessary group should re-render not all. Because in our
app we can have more than 1000 plus group list and re-rendering 1000 plus list is performance
inefficient job. Hence while connecting group component to state, we are using the key (uid) of
the user to subscribe for only the change of that state value in userOnlineStatus Map.
When user visits the webapp at first, we connect the socket with the server and after the
successful connection we subscribe to groups that will provide the list of groups that user have,
after getting the list of groups we can dispatch the total groups.
When subscribing to the user, we get user online status and after the necessary modification done
to create map data structure, we can dispatch the userOnlineStatus map.
When any user comes online, we read that in user_online event from web socket and based on
the payload (user details) we dispatch the action and reducer will take care of changing the state.
Chapter 8
8.1 Webrtc
8.1.1 Introduction
WebRTC (Web Real-Time Communication) is an open-source technology that enables real-time
communication between browsers and mobile applications using a peer-to-peer (P2P) approach.
It provides APIs and protocols that allow web developers to add real-time communication
capabilities to their applications, without requiring any additional plugins or software.
WebRTC was developed by Google in 2011 and is now supported by major web browsers such
as Chrome, Firefox, Safari, and Edge. It has quickly become a popular technology for building
real-time communication applications, such as video and audio chat, file sharing, and screen
sharing.
WebRTC works by using a combination of JavaScript APIs, signaling protocols, and media
codecs to establish a P2P connection between browsers. Once a connection is established, the
browsers can exchange audio, video, and data directly, without the need for a server to mediate
the communication.
Some of the key features of WebRTC include:
i) Support for real-time audio and video communication
ii) Low latency and high-quality audio and video transmission
iii) Secure peer-to-peer communication using encryption
iv) Support for NAT and firewall traversal to enable communication between devices behind
different network configurations
v) Easy integration with existing web technologies and frameworks
8.1.2 My learning
During my exploration of WebRTC, I discovered that it is a powerful and flexible technology that
enables real-time communication between browsers and mobile applications. It provides a way
for developers to add audio, video, and data sharing capabilities to their applications, without
requiring any additional software or plugins.
8.2 Janus.js
8.2.1 Introduction
Janus.js is a JavaScript library for building WebRTC-based real-time communication
applications. It provides a flexible and modular framework for developing applications that use
WebRTC, including video conferencing, streaming, and recording.
Janus.js is built on top of the Janus WebRTC server, which is a general purpose WebRTC server
that provides a range of capabilities for managing WebRTC sessions and interactions. The
Janus.js library provides an easy-to-use interface for interacting with the Janus server, making it
easy to build complex real-time communication applications in the browser.
Some of the key features of Janus.js include:
i) Modular design: Janus.js is built with a modular architecture that makes it easy to add
and remove functionality as needed. This allows developers to build applications that are
tailored to their specific requirements, without having to include unnecessary features or
components.
ii) Easy integration: Janus.js can be easily integrated with other web technologies and
frameworks, such as React, Angular, and Vue. This makes it easy to build real-time
communication applications that are fully integrated with other parts of a web
application.
iii) Customizable user interface: Janus.js provides a set of customizable user interface
components, such as buttons, dialogs, and forms, that can be used to build rich and
engaging user interfaces for real-time communication applications.
iv) Scalability: Janus.js is designed to be scalable, allowing it to handle large numbers of
WebRTC sessions and interactions. It includes features such as load balancing and
clustering to ensure that applications can handle high levels of traffic and usage.
Janus Audiobridge is a plugin for the Janus WebRTC server that enables audio conferencing
capabilities. It allows multiple participants to join a conference call and communicate with each
other using audio only.
The Janus Audiobridge plugin provides a range of features for managing audio conferences,
including:
i) Support for multiple participants: The Audiobridge plugin allows multiple participants
to join a conference call and communicate with each other using audio. Participants can
join the conference by entering a specific room or by using a unique conference ID.
ii) Dynamic bitrate adjustment: The Audiobridge plugin can dynamically adjust the
bitrate of audio streams based on the available network bandwidth, ensuring that the
audio quality remains high even in low-bandwidth environments.
iii) Advanced echo cancellation: The Audiobridge plugin includes advanced echo
cancellation capabilities to ensure that participants do not experience any feedback or
echo during the conference call.
iv) Flexible configuration options: The Audiobridge plugin includes a range of
configuration options that allow developers to customize the behavior of the plugin to
suit their specific requirements. This includes options for managing bandwidth, audio
quality, and participant permissions.
Chapter 9
i) When someone lineOn in the group it broadcasts its line_on status to all the group
members who are online. Upon receiving the line_on event they will join the Janus
room if not already joined.
ii) After joining room, they will all be ready to listen to the voice media from another users.
iii) It is possible to listen to the voice media from two different groups simultaneously.
iv) But it is not talk to the two groups at the same time.
v) After getting all the line_on signal from different groups the user can click and decide
where he/she wants to talk. Upon clicking on the talk/call button we will mute all voices
from the other groups and will allow the user to talk or listen to choose room/group.
vi) And after lineOff the group we will unmute all the already active group again to listen
the audio from all the active groups.
vii) These are some edge cases that I have handled and were the deciding factor of our
business logic.
Chapter 10
At this point I was instructed to implement a message feature to send text messages, recorded
voice notes and file transfer.
And it broadcasts the message to all the online users in the group with given groupid in payload.
i) User can send the text message to the other users, here in this case the type in the
payload is “type: text”
ii) Fig shows the text message sent in the group.
i) Users can send the voice recording in the group same as what we can do in WhatsApp,
here the type of message in the payload in “mediaURL” which stored the URL to the
media which is saved in firebase storage.
ii) Fig shows the voice recording sent in the group.
i) We are storing the payload given in the group_message event in the firebase Realtime
database at a location referring to the groupid.
ii) Storing of message payload is done at backend.
i) Before emitting group_message event with the payload, we save the voice note and file to
the firebase storage if user sent voice recording or file.
ii) After saving the file successfully in firebase storage the url (referring to the location in
storage) is sent with the payload. MediaURL for the voice note and just url for the file.
iii) Another user can download the file and see the preview modal of the file and can listen
to the voice recording.
There is another functionality that the user can send the text with the media file.