Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
08ffc79a65 | |||
2a72b198e3 | |||
0d085a2b4d | |||
497f9e882c | |||
7d97d10e76 | |||
8305dd561d | |||
e97bb519ed | |||
18acde5b2b | |||
bab4732221 | |||
79af695d17 | |||
d98312f99b | |||
010bb6a102 | |||
530e08b9ee |
File diff suppressed because one or more lines are too long
@ -1,9 +1,10 @@
|
||||
import { COMMAND } from 'state/actions';
|
||||
import { join, part, invite, kick, setTopic } from 'state/channels';
|
||||
import { sendMessage, raw } from 'state/messages';
|
||||
import { openPrivateChat } from 'state/privateChats';
|
||||
import { setNick, disconnect, whois, away } from 'state/servers';
|
||||
import { select } from 'state/tab';
|
||||
import { find } from 'utils';
|
||||
import { find, isChannel } from 'utils';
|
||||
import createCommandMiddleware, {
|
||||
beforeHandler,
|
||||
notFoundHandler
|
||||
@ -45,10 +46,10 @@ export default createCommandMiddleware(COMMAND, {
|
||||
}
|
||||
},
|
||||
|
||||
part({ dispatch, server, channel, isChannel }, partChannel) {
|
||||
part({ dispatch, server, channel, inChannel }, partChannel) {
|
||||
if (partChannel) {
|
||||
dispatch(part([partChannel], server));
|
||||
} else if (isChannel) {
|
||||
} else if (inChannel) {
|
||||
dispatch(part([channel], server));
|
||||
} else {
|
||||
return error('This is not a channel');
|
||||
@ -98,6 +99,9 @@ export default createCommandMiddleware(COMMAND, {
|
||||
const msg = message.join(' ');
|
||||
if (msg !== '') {
|
||||
dispatch(sendMessage(message.join(' '), target, server));
|
||||
if (!isChannel(target)) {
|
||||
dispatch(openPrivateChat(server, target));
|
||||
}
|
||||
dispatch(select(server, target));
|
||||
} else {
|
||||
return error('Messages can not be empty');
|
||||
@ -117,8 +121,8 @@ export default createCommandMiddleware(COMMAND, {
|
||||
}
|
||||
},
|
||||
|
||||
invite({ dispatch, server, channel, isChannel }, user, inviteChannel) {
|
||||
if (!inviteChannel && !isChannel) {
|
||||
invite({ dispatch, server, channel, inChannel }, user, inviteChannel) {
|
||||
if (!inviteChannel && !inChannel) {
|
||||
return error('This is not a channel');
|
||||
}
|
||||
|
||||
@ -131,8 +135,8 @@ export default createCommandMiddleware(COMMAND, {
|
||||
}
|
||||
},
|
||||
|
||||
kick({ dispatch, server, channel, isChannel }, user) {
|
||||
if (!isChannel) {
|
||||
kick({ dispatch, server, channel, inChannel }, user) {
|
||||
if (!inChannel) {
|
||||
return error('This is not a channel');
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { Suspense, lazy, useState } from 'react';
|
||||
import React, { Suspense, lazy, useState, useEffect } from 'react';
|
||||
import Route from 'containers/Route';
|
||||
import AppInfo from 'components/AppInfo';
|
||||
import TabList from 'components/TabList';
|
||||
@ -28,6 +28,11 @@ const App = ({
|
||||
setRenderModals(true);
|
||||
}
|
||||
|
||||
const [starting, setStarting] = useState(true);
|
||||
useEffect(() => {
|
||||
setTimeout(() => setStarting(false), 1000);
|
||||
}, []);
|
||||
|
||||
const mainClass = cn('main-container', {
|
||||
'off-canvas': showTabList
|
||||
});
|
||||
@ -40,7 +45,7 @@ const App = ({
|
||||
|
||||
return (
|
||||
<div className="wrap" onClick={handleClick}>
|
||||
{!connected && (
|
||||
{!starting && !connected && (
|
||||
<AppInfo type="error">
|
||||
Connection lost, attempting to reconnect...
|
||||
</AppInfo>
|
||||
|
@ -61,7 +61,7 @@ export default class TabList extends PureComponent {
|
||||
<div
|
||||
key={`${address}-chans}`}
|
||||
className="tab-label"
|
||||
onClick={() => openModal('channel', { server: address })}
|
||||
onClick={() => openModal('channel', address)}
|
||||
>
|
||||
<span>CHANNELS {chanLabel}</span>
|
||||
<Button title="Join Channel">+</Button>
|
||||
|
@ -1,20 +1,23 @@
|
||||
import React, { memo, useState, useEffect, useCallback, useRef } from 'react';
|
||||
import get from 'lodash/get';
|
||||
import React, { memo, useState, useEffect, useRef } from 'react';
|
||||
import Modal from 'react-modal';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { FiUsers, FiX } from 'react-icons/fi';
|
||||
import withModal from 'components/modals/withModal';
|
||||
import useModal from 'components/modals/useModal';
|
||||
import Button from 'components/ui/Button';
|
||||
import { join } from 'state/channels';
|
||||
import { select } from 'state/tab';
|
||||
import { searchChannels } from 'state/channelSearch';
|
||||
import { linkify } from 'utils';
|
||||
|
||||
const Channel = memo(({ server, name, topic, userCount, joined, ...props }) => {
|
||||
const handleJoinClick = useCallback(() => props.join([name], server), []);
|
||||
const Channel = memo(({ server, name, topic, userCount, joined }) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const handleClick = () => dispatch(join([name], server));
|
||||
|
||||
return (
|
||||
<div className="modal-channel-result">
|
||||
<div className="modal-channel-result-header">
|
||||
<h2 className="modal-channel-name" onClick={handleJoinClick}>
|
||||
<h2 className="modal-channel-name" onClick={handleClick}>
|
||||
{name}
|
||||
</h2>
|
||||
<FiUsers />
|
||||
@ -25,7 +28,7 @@ const Channel = memo(({ server, name, topic, userCount, joined, ...props }) => {
|
||||
<Button
|
||||
className="modal-channel-button-join"
|
||||
category="normal"
|
||||
onClick={handleJoinClick}
|
||||
onClick={handleClick}
|
||||
>
|
||||
Join
|
||||
</Button>
|
||||
@ -36,7 +39,12 @@ const Channel = memo(({ server, name, topic, userCount, joined, ...props }) => {
|
||||
);
|
||||
});
|
||||
|
||||
const AddChannel = ({ search, payload: { server }, onClose, ...props }) => {
|
||||
const AddChannel = () => {
|
||||
const [modal, server, closeModal] = useModal('channel');
|
||||
|
||||
const channels = useSelector(state => state.channels);
|
||||
const search = useSelector(state => state.channelSearch);
|
||||
const dispatch = useDispatch();
|
||||
const [q, setQ] = useState('');
|
||||
|
||||
const inputEl = useRef();
|
||||
@ -44,52 +52,52 @@ const AddChannel = ({ search, payload: { server }, onClose, ...props }) => {
|
||||
const prevSearch = useRef('');
|
||||
|
||||
useEffect(() => {
|
||||
inputEl.current.focus();
|
||||
props.searchChannels(server, '');
|
||||
}, []);
|
||||
if (modal.isOpen) {
|
||||
dispatch(searchChannels(server, ''));
|
||||
setTimeout(() => inputEl.current.focus(), 0);
|
||||
} else {
|
||||
prevSearch.current = '';
|
||||
setQ('');
|
||||
}
|
||||
}, [modal.isOpen]);
|
||||
|
||||
const handleSearch = useCallback(
|
||||
e => {
|
||||
let nextQ = e.target.value.trim().toLowerCase();
|
||||
setQ(nextQ);
|
||||
const handleSearch = e => {
|
||||
let nextQ = e.target.value.trim().toLowerCase();
|
||||
setQ(nextQ);
|
||||
|
||||
if (nextQ !== q) {
|
||||
resultsEl.current.scrollTop = 0;
|
||||
if (nextQ !== q) {
|
||||
resultsEl.current.scrollTop = 0;
|
||||
|
||||
while (nextQ.charAt(0) === '#') {
|
||||
nextQ = nextQ.slice(1);
|
||||
}
|
||||
|
||||
if (nextQ !== prevSearch.current) {
|
||||
prevSearch.current = nextQ;
|
||||
props.searchChannels(server, nextQ);
|
||||
}
|
||||
while (nextQ.charAt(0) === '#') {
|
||||
nextQ = nextQ.slice(1);
|
||||
}
|
||||
},
|
||||
[q]
|
||||
);
|
||||
|
||||
const handleKey = useCallback(e => {
|
||||
if (nextQ !== prevSearch.current) {
|
||||
prevSearch.current = nextQ;
|
||||
dispatch(searchChannels(server, nextQ));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleKey = e => {
|
||||
if (e.key === 'Enter') {
|
||||
let channel = e.target.value.trim();
|
||||
|
||||
if (channel !== '') {
|
||||
onClose(false);
|
||||
closeModal(false);
|
||||
|
||||
if (channel.charAt(0) !== '#') {
|
||||
channel = `#${channel}`;
|
||||
}
|
||||
|
||||
props.join([channel], server);
|
||||
props.select(server, channel);
|
||||
dispatch(join([channel], server));
|
||||
dispatch(select(server, channel));
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
};
|
||||
|
||||
const handleLoadMore = useCallback(
|
||||
() => props.searchChannels(server, q, search.results.length),
|
||||
[q, search.results.length]
|
||||
);
|
||||
const handleLoadMore = () =>
|
||||
dispatch(searchChannels(server, q, search.results.length));
|
||||
|
||||
let hasMore = !search.end;
|
||||
if (hasMore) {
|
||||
@ -104,7 +112,7 @@ const AddChannel = ({ search, payload: { server }, onClose, ...props }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal {...modal}>
|
||||
<div className="modal-channel-input-wrap">
|
||||
<input
|
||||
ref={inputEl}
|
||||
@ -117,7 +125,7 @@ const AddChannel = ({ search, payload: { server }, onClose, ...props }) => {
|
||||
<Button
|
||||
icon={FiX}
|
||||
className="modal-close modal-channel-close"
|
||||
onClick={onClose}
|
||||
onClick={closeModal}
|
||||
/>
|
||||
</div>
|
||||
<div ref={resultsEl} className="modal-channel-results">
|
||||
@ -125,12 +133,7 @@ const AddChannel = ({ search, payload: { server }, onClose, ...props }) => {
|
||||
<Channel
|
||||
key={`${server} ${channel.name}`}
|
||||
server={server}
|
||||
join={props.join}
|
||||
joined={get(
|
||||
props.channels,
|
||||
[server, channel.name, 'joined'],
|
||||
false
|
||||
)}
|
||||
joined={channels[server]?.[channel.name]?.joined}
|
||||
{...channel}
|
||||
/>
|
||||
))}
|
||||
@ -143,15 +146,8 @@ const AddChannel = ({ search, payload: { server }, onClose, ...props }) => {
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default withModal({
|
||||
name: 'channel',
|
||||
state: {
|
||||
channels: state => state.channels,
|
||||
search: state => state.channelSearch
|
||||
},
|
||||
actions: { searchChannels, join, select }
|
||||
})(AddChannel);
|
||||
export default AddChannel;
|
||||
|
@ -1,27 +1,26 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import withModal from 'components/modals/withModal';
|
||||
import React from 'react';
|
||||
import Modal from 'react-modal';
|
||||
import useModal from 'components/modals/useModal';
|
||||
import Button from 'components/ui/Button';
|
||||
|
||||
const Confirm = ({
|
||||
payload: { question, confirmation, onConfirm },
|
||||
onClose
|
||||
}) => {
|
||||
const handleConfirm = useCallback(() => {
|
||||
onClose(false);
|
||||
const Confirm = () => {
|
||||
const [modal, payload, closeModal] = useModal('confirm');
|
||||
const { question, confirmation, onConfirm } = payload;
|
||||
|
||||
const handleConfirm = () => {
|
||||
closeModal(false);
|
||||
onConfirm();
|
||||
}, []);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal {...modal}>
|
||||
<p>{question}</p>
|
||||
<Button onClick={handleConfirm}>{confirmation || 'OK'}</Button>
|
||||
<Button category="normal" onClick={onClose}>
|
||||
<Button category="normal" onClick={closeModal}>
|
||||
Cancel
|
||||
</Button>
|
||||
</>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default withModal({
|
||||
name: 'confirm'
|
||||
})(Confirm);
|
||||
export default Confirm;
|
||||
|
@ -1,21 +1,26 @@
|
||||
import React from 'react';
|
||||
import Modal from 'react-modal';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { FiX } from 'react-icons/fi';
|
||||
import Button from 'components/ui/Button';
|
||||
import withModal from 'components/modals/withModal';
|
||||
import useModal from 'components/modals/useModal';
|
||||
import { getSelectedChannel } from 'state/channels';
|
||||
import { linkify } from 'utils';
|
||||
|
||||
const Topic = ({ payload: { topic, channel }, onClose }) => {
|
||||
const Topic = () => {
|
||||
const [modal, channel, closeModal] = useModal('topic');
|
||||
|
||||
const topic = useSelector(state => getSelectedChannel(state)?.topic);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal {...modal}>
|
||||
<div className="modal-header">
|
||||
<h2>Topic in {channel}</h2>
|
||||
<Button icon={FiX} className="modal-close" onClick={onClose} />
|
||||
<Button icon={FiX} className="modal-close" onClick={closeModal} />
|
||||
</div>
|
||||
<p className="modal-content">{linkify(topic)}</p>
|
||||
</>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default withModal({
|
||||
name: 'topic'
|
||||
})(Topic);
|
||||
export default Topic;
|
||||
|
46
client/js/components/modals/useModal.js
Normal file
46
client/js/components/modals/useModal.js
Normal file
@ -0,0 +1,46 @@
|
||||
import { useCallback } from 'react';
|
||||
import Modal from 'react-modal';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { closeModal } from 'state/modals';
|
||||
|
||||
Modal.setAppElement('#root');
|
||||
|
||||
const defaultPayload = {};
|
||||
|
||||
export default function useModal(name) {
|
||||
const isOpen = useSelector(state => state.modals[name]?.isOpen || false);
|
||||
const payload = useSelector(
|
||||
state => state.modals[name]?.payload || defaultPayload
|
||||
);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const handleRequestClose = useCallback(
|
||||
(dismissed = true) => {
|
||||
dispatch(closeModal(name));
|
||||
|
||||
if (dismissed && payload.onDismiss) {
|
||||
payload.onDismiss();
|
||||
}
|
||||
},
|
||||
[payload.onDismiss]
|
||||
);
|
||||
|
||||
const modalProps = {
|
||||
isOpen,
|
||||
contentLabel: name,
|
||||
onRequestClose: handleRequestClose,
|
||||
className: {
|
||||
base: `modal modal-${name}`,
|
||||
afterOpen: 'modal-opening',
|
||||
beforeClose: 'modal-closing'
|
||||
},
|
||||
overlayClassName: {
|
||||
base: 'modal-overlay',
|
||||
afterOpen: 'modal-overlay-opening',
|
||||
beforeClose: 'modal-overlay-closing'
|
||||
},
|
||||
closeTimeoutMS: 200
|
||||
};
|
||||
|
||||
return [modalProps, payload, handleRequestClose];
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import Modal from 'react-modal';
|
||||
import { createStructuredSelector } from 'reselect';
|
||||
import get from 'lodash/get';
|
||||
import { getModals, closeModal } from 'state/modals';
|
||||
import connect from 'utils/connect';
|
||||
import { bindActionCreators } from 'redux';
|
||||
|
||||
Modal.setAppElement('#root');
|
||||
|
||||
export default function withModal({ name, ...modalProps }) {
|
||||
modalProps = {
|
||||
className: {
|
||||
base: `modal modal-${name}`,
|
||||
afterOpen: 'modal-opening',
|
||||
beforeClose: 'modal-closing'
|
||||
},
|
||||
overlayClassName: {
|
||||
base: 'modal-overlay',
|
||||
afterOpen: 'modal-overlay-opening',
|
||||
beforeClose: 'modal-overlay-closing'
|
||||
},
|
||||
closeTimeoutMS: 200,
|
||||
...modalProps
|
||||
};
|
||||
|
||||
return WrappedComponent => {
|
||||
const ReduxModal = ({ onRequestClose, ...props }) => {
|
||||
const handleRequestClose = useCallback(
|
||||
(dismissed = true) => {
|
||||
onRequestClose();
|
||||
|
||||
if (dismissed && props.payload.onDismiss) {
|
||||
props.payload.onDismiss();
|
||||
}
|
||||
},
|
||||
[props.payload.onDismiss]
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
contentLabel={name}
|
||||
onRequestClose={handleRequestClose}
|
||||
{...modalProps}
|
||||
{...props}
|
||||
>
|
||||
<WrappedComponent onClose={handleRequestClose} {...props} />
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
const mapState = createStructuredSelector({
|
||||
isOpen: state => get(getModals(state), [name, 'isOpen'], false),
|
||||
payload: state => get(getModals(state), [name, 'payload'], {}),
|
||||
...modalProps.state
|
||||
});
|
||||
|
||||
const mapDispatch = dispatch => {
|
||||
const actions = { onRequestClose: () => dispatch(closeModal(name)) };
|
||||
if (modalProps.actions) {
|
||||
return {
|
||||
...actions,
|
||||
...bindActionCreators(modalProps.actions, dispatch)
|
||||
};
|
||||
}
|
||||
return actions;
|
||||
};
|
||||
|
||||
return connect(mapState, mapDispatch)(ReduxModal);
|
||||
};
|
||||
}
|
@ -50,12 +50,7 @@ const ChatTitle = ({
|
||||
{channel && channel.topic && (
|
||||
<span
|
||||
className="chat-topic"
|
||||
onClick={() =>
|
||||
openModal('topic', {
|
||||
topic: channel.topic,
|
||||
channel: channel.name
|
||||
})
|
||||
}
|
||||
onClick={() => openModal('topic', channel.name)}
|
||||
>
|
||||
{channel.topic}
|
||||
</span>
|
||||
|
@ -5,7 +5,7 @@ export const beforeHandler = '_before';
|
||||
export const notFoundHandler = 'commandNotFound';
|
||||
|
||||
function createContext({ dispatch, getState }, { server, channel }) {
|
||||
return { dispatch, getState, server, channel, isChannel: isChannel(channel) };
|
||||
return { dispatch, getState, server, channel, inChannel: isChannel(channel) };
|
||||
}
|
||||
|
||||
// TODO: Pull this out as convenience action
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { socket as socketActions } from 'state/actions';
|
||||
import { getWrapWidth, appSet } from 'state/app';
|
||||
import { getConnected, getWrapWidth, appSet } from 'state/app';
|
||||
import { searchChannels } from 'state/channelSearch';
|
||||
import { addMessages } from 'state/messages';
|
||||
import { setSettings } from 'state/settings';
|
||||
import { when } from 'utils/observe';
|
||||
@ -12,6 +13,13 @@ function loadState({ store }, env) {
|
||||
type: socketActions.SERVERS,
|
||||
data: env.servers
|
||||
});
|
||||
|
||||
when(store, getConnected, () =>
|
||||
// Cache top channels for each server
|
||||
env.servers.forEach(({ host }) =>
|
||||
store.dispatch(searchChannels(host, ''))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (env.channels) {
|
||||
@ -21,6 +29,13 @@ function loadState({ store }, env) {
|
||||
});
|
||||
}
|
||||
|
||||
if (env.openDMs) {
|
||||
store.dispatch({
|
||||
type: 'PRIVATE_CHATS',
|
||||
privateChats: env.openDMs
|
||||
});
|
||||
}
|
||||
|
||||
if (env.users) {
|
||||
store.dispatch({
|
||||
type: socketActions.USERS,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import Cookie from 'js-cookie';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { getSelectedTab } from 'state/tab';
|
||||
import { isChannel, stringifyTab } from 'utils';
|
||||
import { stringifyTab } from 'utils';
|
||||
import { observe } from 'utils/observe';
|
||||
|
||||
const saveTab = debounce(
|
||||
@ -11,7 +11,7 @@ const saveTab = debounce(
|
||||
|
||||
export default function storage({ store }) {
|
||||
observe(store, getSelectedTab, tab => {
|
||||
if (isChannel(tab) || (tab.server && !tab.name)) {
|
||||
if (tab.server) {
|
||||
saveTab(tab);
|
||||
}
|
||||
});
|
||||
|
@ -250,6 +250,33 @@ describe('message reducer', () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('deletes direct messages when closing a direct message tab', () => {
|
||||
let state = {
|
||||
srv: {
|
||||
bob: [{ content: 'msg1' }, { content: 'msg2' }],
|
||||
'#chan2': [{ content: 'msg' }]
|
||||
},
|
||||
srv2: {
|
||||
'#chan1': [{ content: 'msg' }]
|
||||
}
|
||||
};
|
||||
|
||||
state = reducer(state, {
|
||||
type: actions.CLOSE_PRIVATE_CHAT,
|
||||
server: 'srv',
|
||||
nick: 'bob'
|
||||
});
|
||||
|
||||
expect(state).toEqual({
|
||||
srv: {
|
||||
'#chan2': [{ content: 'msg' }]
|
||||
},
|
||||
srv2: {
|
||||
'#chan1': [{ content: 'msg' }]
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getMessageTab()', () => {
|
||||
|
@ -26,6 +26,7 @@ export const CLOSE_MODAL = 'CLOSE_MODAL';
|
||||
|
||||
export const CLOSE_PRIVATE_CHAT = 'CLOSE_PRIVATE_CHAT';
|
||||
export const OPEN_PRIVATE_CHAT = 'OPEN_PRIVATE_CHAT';
|
||||
export const PRIVATE_CHATS = 'PRIVATE_CHATS';
|
||||
|
||||
export const SEARCH_MESSAGES = 'SEARCH_MESSAGES';
|
||||
export const TOGGLE_SEARCH = 'TOGGLE_SEARCH';
|
||||
|
@ -9,7 +9,7 @@ export const getWindowWidth = state => state.app.windowWidth;
|
||||
export const getConnectDefaults = state => state.app.connectDefaults;
|
||||
|
||||
const initialState = {
|
||||
connected: true,
|
||||
connected: false,
|
||||
wrapWidth: 0,
|
||||
charWidth: 0,
|
||||
windowWidth: 0,
|
||||
|
@ -3,11 +3,12 @@ import * as actions from 'state/actions';
|
||||
|
||||
const initialState = {
|
||||
results: [],
|
||||
end: false
|
||||
end: false,
|
||||
topCache: {}
|
||||
};
|
||||
|
||||
export default createReducer(initialState, {
|
||||
[actions.socket.CHANNEL_SEARCH](state, { results, start }) {
|
||||
[actions.socket.CHANNEL_SEARCH](state, { results, start, server, q }) {
|
||||
if (results) {
|
||||
state.end = false;
|
||||
|
||||
@ -15,15 +16,20 @@ export default createReducer(initialState, {
|
||||
state.results.push(...results);
|
||||
} else {
|
||||
state.results = results;
|
||||
|
||||
if (!q) {
|
||||
state.topCache[server] = results;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
state.end = true;
|
||||
}
|
||||
},
|
||||
|
||||
[actions.OPEN_MODAL](state, { name }) {
|
||||
[actions.OPEN_MODAL](state, { name, payload }) {
|
||||
if (name === 'channel') {
|
||||
return initialState;
|
||||
state.results = state.topCache[payload] || [];
|
||||
state.end = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -140,6 +140,10 @@ export default createReducer(
|
||||
channels.forEach(channel => delete state[server][channel]);
|
||||
},
|
||||
|
||||
[actions.CLOSE_PRIVATE_CHAT](state, { server, nick }) {
|
||||
delete state[server][nick];
|
||||
},
|
||||
|
||||
[actions.socket.CHANNEL_FORWARD](state, { server, old }) {
|
||||
if (state[server]) {
|
||||
delete state[server][old];
|
||||
|
@ -1,5 +1,4 @@
|
||||
import sortBy from 'lodash/sortBy';
|
||||
import { findIndex } from 'utils';
|
||||
import createReducer from 'utils/createReducer';
|
||||
import { updateSelection } from './tab';
|
||||
import * as actions from './actions';
|
||||
@ -10,7 +9,7 @@ function open(state, server, nick) {
|
||||
if (!state[server]) {
|
||||
state[server] = [];
|
||||
}
|
||||
if (findIndex(state[server], n => n === nick) === -1) {
|
||||
if (!state[server].includes(nick)) {
|
||||
state[server].push(nick);
|
||||
state[server] = sortBy(state[server], v => v.toLowerCase());
|
||||
}
|
||||
@ -24,12 +23,22 @@ export default createReducer(
|
||||
},
|
||||
|
||||
[actions.CLOSE_PRIVATE_CHAT](state, { server, nick }) {
|
||||
const i = findIndex(state[server], n => n === nick);
|
||||
const i = state[server]?.findIndex(n => n === nick);
|
||||
if (i !== -1) {
|
||||
state[server].splice(i, 1);
|
||||
}
|
||||
},
|
||||
|
||||
[actions.PRIVATE_CHATS](state, { privateChats }) {
|
||||
privateChats.forEach(({ server, name }) => {
|
||||
if (!state[server]) {
|
||||
state[server] = [];
|
||||
}
|
||||
|
||||
state[server].push(name);
|
||||
});
|
||||
},
|
||||
|
||||
[actions.socket.PM](state, action) {
|
||||
if (action.from.indexOf('.') === -1) {
|
||||
open(state, action.server, action.from);
|
||||
@ -43,10 +52,18 @@ export default createReducer(
|
||||
);
|
||||
|
||||
export function openPrivateChat(server, nick) {
|
||||
return {
|
||||
type: actions.OPEN_PRIVATE_CHAT,
|
||||
server,
|
||||
nick
|
||||
return (dispatch, getState) => {
|
||||
if (!getState().privateChats[server]?.includes(nick)) {
|
||||
dispatch({
|
||||
type: actions.OPEN_PRIVATE_CHAT,
|
||||
server,
|
||||
nick,
|
||||
socket: {
|
||||
type: 'open_dm',
|
||||
data: { server, name: nick }
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -55,7 +72,11 @@ export function closePrivateChat(server, nick) {
|
||||
dispatch({
|
||||
type: actions.CLOSE_PRIVATE_CHAT,
|
||||
server,
|
||||
nick
|
||||
nick,
|
||||
socket: {
|
||||
type: 'close_dm',
|
||||
data: { server, name: nick }
|
||||
}
|
||||
});
|
||||
dispatch(updateSelection());
|
||||
};
|
||||
|
@ -1,25 +1,5 @@
|
||||
/* eslint-disable no-bitwise */
|
||||
import { hsluvToHex } from 'hsluv';
|
||||
|
||||
//
|
||||
// github.com/sindresorhus/fnv1a
|
||||
//
|
||||
const OFFSET_BASIS_32 = 2166136261;
|
||||
|
||||
const fnv1a = string => {
|
||||
let hash = OFFSET_BASIS_32;
|
||||
|
||||
for (let i = 0; i < string.length; i++) {
|
||||
hash ^= string.charCodeAt(i);
|
||||
|
||||
// 32-bit FNV prime: 2**24 + 2**8 + 0x93 = 16777619
|
||||
// Using bitshift for accuracy and performance. Numbers in JS suck.
|
||||
hash +=
|
||||
(hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
|
||||
}
|
||||
|
||||
return hash >>> 0;
|
||||
};
|
||||
import fnv1a from '@sindresorhus/fnv1a';
|
||||
|
||||
const colors = [];
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
"@babel/preset-env": "^7.9.5",
|
||||
"@babel/preset-react": "^7.9.4",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-jest": "^25.5.0",
|
||||
"babel-jest": "^26.0.1",
|
||||
"babel-loader": "^8.1.0",
|
||||
"brotli": "^1.3.1",
|
||||
"copy-webpack-plugin": "^5.1.1",
|
||||
@ -37,12 +37,12 @@
|
||||
"eslint-plugin-import": "^2.20.2",
|
||||
"eslint-plugin-jsx-a11y": "^6.2.3",
|
||||
"eslint-plugin-react": "^7.19.0",
|
||||
"eslint-plugin-react-hooks": "^3.0.0",
|
||||
"eslint-plugin-react-hooks": "^4.0.0",
|
||||
"express": "^4.17.1",
|
||||
"express-http-proxy": "^1.6.0",
|
||||
"gulp": "4.0.2",
|
||||
"gulp-util": "^3.0.8",
|
||||
"jest": "^25.5.0",
|
||||
"jest": "^26.0.1",
|
||||
"mini-css-extract-plugin": "^0.9.0",
|
||||
"postcss-flexbugs-fixes": "^4.2.1",
|
||||
"postcss-loader": "^3.0.0",
|
||||
@ -50,7 +50,7 @@
|
||||
"prettier": "2.0.5",
|
||||
"react-test-renderer": "16.13.1",
|
||||
"style-loader": "^1.2.1",
|
||||
"terser-webpack-plugin": "^2.3.6",
|
||||
"terser-webpack-plugin": "^3.0.1",
|
||||
"through2": "^3.0.1",
|
||||
"webpack": "^4.43.0",
|
||||
"webpack-dev-middleware": "^3.7.2",
|
||||
@ -59,6 +59,7 @@
|
||||
"workbox-webpack-plugin": "^5.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sindresorhus/fnv1a": "^2.0.0",
|
||||
"autolinker": "^3.14.1",
|
||||
"backo": "^1.1.0",
|
||||
"classnames": "^2.2.6",
|
||||
@ -66,12 +67,12 @@
|
||||
"formik": "^2.1.4",
|
||||
"history": "^5.0.0-beta.8",
|
||||
"hsluv": "^0.1.0",
|
||||
"immer": "^6.0.3",
|
||||
"immer": "^6.0.5",
|
||||
"js-cookie": "^2.2.1",
|
||||
"lodash": "^4.17.15",
|
||||
"react": "16.13.1",
|
||||
"react-dom": "16.13.1",
|
||||
"react-hot-loader": "^4.12.20",
|
||||
"react-hot-loader": "^4.12.21",
|
||||
"react-icons": "^3.7.0",
|
||||
"react-modal": "^3.11.2",
|
||||
"react-redux": "^7.2.0",
|
||||
|
@ -90,13 +90,7 @@ module.exports = {
|
||||
revision: '__INDEX_REVISON__'
|
||||
}
|
||||
],
|
||||
exclude: [
|
||||
/\.map$/,
|
||||
/^manifest.*\.js(?:on)?$/,
|
||||
/^boot.*\.js$/,
|
||||
/^runtime.*\.js$/,
|
||||
/\.txt$/
|
||||
]
|
||||
exclude: [/\.map$/, /^boot.*\.js$/, /^runtime.*\.js$/, /\.txt$/]
|
||||
})
|
||||
],
|
||||
optimization: {
|
||||
|
2743
client/yarn.lock
2743
client/yarn.lock
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@ verify_certificates = true
|
||||
|
||||
# Defaults for the client connect form
|
||||
[defaults]
|
||||
name = "Freenode"
|
||||
name = "freenode"
|
||||
host = "chat.freenode.net"
|
||||
port = 6697
|
||||
channels = [
|
||||
|
14
go.mod
14
go.mod
@ -17,13 +17,13 @@ require (
|
||||
github.com/fsnotify/fsnotify v1.4.9
|
||||
github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a // indirect
|
||||
github.com/go-acme/lego/v3 v3.6.0 // indirect
|
||||
github.com/golang/protobuf v1.4.0 // indirect
|
||||
github.com/golang/protobuf v1.4.1 // indirect
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/jmhodges/levigo v1.0.0 // indirect
|
||||
github.com/jpillora/backoff v1.0.0
|
||||
github.com/kjk/betterguid v0.0.0-20170621091430-c442874ba63a
|
||||
github.com/klauspost/cpuid v1.2.3
|
||||
github.com/mailru/easyjson v0.7.1
|
||||
github.com/klauspost/cpuid v1.2.4
|
||||
github.com/mailru/easyjson v0.7.2-0.20200424172602-f0a000e7a8e0
|
||||
github.com/miekg/dns v1.1.29 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/mitchellh/mapstructure v1.3.0 // indirect
|
||||
@ -42,9 +42,9 @@ require (
|
||||
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect
|
||||
github.com/tinylib/msgp v1.1.2 // indirect
|
||||
go.etcd.io/bbolt v1.3.4
|
||||
golang.org/x/crypto v0.0.0-20200427165652-729f1e841bcc // indirect
|
||||
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0
|
||||
golang.org/x/sys v0.0.0-20200428200454-593003d681fa // indirect
|
||||
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 // indirect
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f
|
||||
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 // indirect
|
||||
gopkg.in/ini.v1 v1.55.0 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.5.0 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
|
||||
)
|
||||
|
18
go.sum
18
go.sum
@ -192,6 +192,8 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
@ -246,6 +248,8 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht
|
||||
github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U=
|
||||
github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
@ -266,6 +270,8 @@ github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid v1.2.3 h1:CCtW0xUnWGVINKvE/WWOYKdsPV6mawAtvQuSl8guwQs=
|
||||
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid v1.2.4 h1:EBfaK0SWSwk+fgk6efYFWdzl8MwRWoOO1gkmiaTXPW4=
|
||||
github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/kljensen/snowball v0.6.0 h1:6DZLCcZeL0cLfodx+Md4/OLC6b/bfurWUOUGs1ydfOU=
|
||||
github.com/kljensen/snowball v0.6.0/go.mod h1:27N7E8fVU5H68RlUmnWwZCfxgt4POBJfENGMvNRhldw=
|
||||
github.com/kolo/xmlrpc v0.0.0-20190717152603-07c4ee3fd181/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ=
|
||||
@ -287,6 +293,8 @@ github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzR
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.7.1 h1:mdxE1MF9o53iCb2Ghj1VfWvh7ZOwHpnVG/xwXrV90U8=
|
||||
github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
|
||||
github.com/mailru/easyjson v0.7.2-0.20200424172602-f0a000e7a8e0 h1:kBQYXw1PdcnwYP5hntk8LEDPdq++fubPN76BlfGLdIM=
|
||||
github.com/mailru/easyjson v0.7.2-0.20200424172602-f0a000e7a8e0/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
@ -490,6 +498,8 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqp
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200427165652-729f1e841bcc h1:ZGI/fILM2+ueot/UixBSoj9188jCAxVHEZEGhqq67I4=
|
||||
golang.org/x/crypto v0.0.0-20200427165652-729f1e841bcc/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 h1:IaQbIIB2X/Mp/DKctl6ROxz1KyMlKp4uyvL6+kQ7C88=
|
||||
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@ -550,6 +560,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0 h1:Jcxah/M+oLZ/R4/z5RzfPzGbPXnVDPkEDtf2JnuxN+U=
|
||||
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f h1:QBjCr1Fz5kw158VqdE9JfI9cJnl/ymnJWAdMuinqL7Y=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@ -602,6 +614,8 @@ golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200428200454-593003d681fa h1:yMbJOvnfYkO1dSAviTu/ZguZWLBTXx4xE3LYrxUCCiA=
|
||||
golang.org/x/sys v0.0.0-20200428200454-593003d681fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 h1:5B6i6EAiSYyejWfvc5Rc9BbI3rzIsrrXfAQBWnYfn+w=
|
||||
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@ -700,6 +714,8 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0 h1:cJv5/xdbk1NnMPR1VP9+HU6gupuG9MLBoH1r6RHZ2MY=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
@ -723,6 +739,8 @@ gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4
|
||||
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/square/go-jose.v2 v2.5.0 h1:OZ4sdq+Y+SHfYB7vfthi1Ei8b0vkP8ZPQgUfUwdUSqo=
|
||||
gopkg.in/square/go-jose.v2 v2.5.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
|
||||
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/jpillora/backoff"
|
||||
)
|
||||
@ -54,6 +55,8 @@ func NewClient(nick, username string) *Client {
|
||||
reconnect: make(chan struct{}),
|
||||
recvBuf: make([]byte, 0, 4096),
|
||||
backoff: &backoff.Backoff{
|
||||
Min: 500 * time.Millisecond,
|
||||
Max: 30 * time.Second,
|
||||
Jitter: true,
|
||||
},
|
||||
}
|
||||
|
@ -79,6 +79,7 @@ func (c *Client) run() {
|
||||
c.sendRecv.Wait()
|
||||
c.reconnect = make(chan struct{})
|
||||
|
||||
time.Sleep(c.backoff.Duration())
|
||||
c.tryConnect()
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ const indexTemplate = `
|
||||
{{end}}
|
||||
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
<link rel="apple-touch-icon" href="/icon_192.png">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
@ -31,6 +31,7 @@ type indexData struct {
|
||||
Defaults *config.Defaults
|
||||
Servers []Server
|
||||
Channels []*storage.Channel
|
||||
OpenDMs []storage.Tab
|
||||
HexIP bool
|
||||
Version dispatchVersion
|
||||
|
||||
@ -43,7 +44,7 @@ type indexData struct {
|
||||
Messages *Messages
|
||||
}
|
||||
|
||||
func (d *Dispatch) getIndexData(r *http.Request, path string, state *State) *indexData {
|
||||
func (d *Dispatch) getIndexData(r *http.Request, state *State) *indexData {
|
||||
cfg := d.Config()
|
||||
|
||||
data := indexData{
|
||||
@ -98,35 +99,37 @@ func (d *Dispatch) getIndexData(r *http.Request, path string, state *State) *ind
|
||||
}
|
||||
data.Channels = channels
|
||||
|
||||
server, channel := getTabFromPath(path)
|
||||
if isInChannel(channels, server, channel) {
|
||||
data.addUsersAndMessages(server, channel, state)
|
||||
return &data
|
||||
openDMs, err := state.user.GetOpenDMs()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
data.OpenDMs = openDMs
|
||||
|
||||
server, channel = parseTabCookie(r, path)
|
||||
if isInChannel(channels, server, channel) {
|
||||
data.addUsersAndMessages(server, channel, state)
|
||||
tab, err := tabFromRequest(r)
|
||||
if err == nil && hasTab(channels, openDMs, tab.Server, tab.Name) {
|
||||
data.addUsersAndMessages(tab.Server, tab.Name, state)
|
||||
}
|
||||
|
||||
return &data
|
||||
}
|
||||
|
||||
func (d *indexData) addUsersAndMessages(server, channel string, state *State) {
|
||||
users := channelStore.GetUsers(server, channel)
|
||||
if len(users) > 0 {
|
||||
d.Users = &Userlist{
|
||||
Server: server,
|
||||
Channel: channel,
|
||||
Users: users,
|
||||
func (d *indexData) addUsersAndMessages(server, name string, state *State) {
|
||||
if isChannel(name) {
|
||||
users := channelStore.GetUsers(server, name)
|
||||
if len(users) > 0 {
|
||||
d.Users = &Userlist{
|
||||
Server: server,
|
||||
Channel: name,
|
||||
Users: users,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
messages, hasMore, err := state.user.GetLastMessages(server, channel, 50)
|
||||
messages, hasMore, err := state.user.GetLastMessages(server, name, 50)
|
||||
if err == nil && len(messages) > 0 {
|
||||
m := Messages{
|
||||
Server: server,
|
||||
To: channel,
|
||||
To: name,
|
||||
Messages: messages,
|
||||
}
|
||||
|
||||
@ -138,10 +141,16 @@ func (d *indexData) addUsersAndMessages(server, channel string, state *State) {
|
||||
}
|
||||
}
|
||||
|
||||
func isInChannel(channels []*storage.Channel, server, channel string) bool {
|
||||
if channel != "" {
|
||||
func hasTab(channels []*storage.Channel, openDMs []storage.Tab, server, name string) bool {
|
||||
if name != "" {
|
||||
for _, ch := range channels {
|
||||
if server == ch.Server && channel == ch.Name {
|
||||
if server == ch.Server && name == ch.Name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
for _, tab := range openDMs {
|
||||
if server == tab.Server && name == tab.Name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -149,30 +158,52 @@ func isInChannel(channels []*storage.Channel, server, channel string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func getTabFromPath(rawPath string) (string, string) {
|
||||
path := strings.Split(strings.Trim(rawPath, "/"), "/")
|
||||
if len(path) >= 2 {
|
||||
name, err := url.PathUnescape(path[len(path)-1])
|
||||
if err == nil && isChannel(name) {
|
||||
return path[len(path)-2], name
|
||||
}
|
||||
}
|
||||
return "", ""
|
||||
}
|
||||
func tabFromRequest(r *http.Request) (Tab, error) {
|
||||
tab := Tab{}
|
||||
|
||||
var path string
|
||||
if strings.HasPrefix(r.URL.Path, "/ws") {
|
||||
path = r.URL.EscapedPath()[3:]
|
||||
} else {
|
||||
referer, err := url.Parse(r.Referer())
|
||||
if err != nil {
|
||||
return tab, err
|
||||
}
|
||||
|
||||
path = referer.EscapedPath()
|
||||
}
|
||||
|
||||
func parseTabCookie(r *http.Request, path string) (string, string) {
|
||||
if path == "/" {
|
||||
cookie, err := r.Cookie("tab")
|
||||
if err == nil {
|
||||
v, err := url.PathUnescape(cookie.Value)
|
||||
if err == nil {
|
||||
tab := strings.SplitN(v, ";", 2)
|
||||
if err != nil {
|
||||
return tab, err
|
||||
}
|
||||
|
||||
if len(tab) == 2 && isChannel(tab[1]) {
|
||||
return tab[0], tab[1]
|
||||
v, err := url.PathUnescape(cookie.Value)
|
||||
if err != nil {
|
||||
return tab, err
|
||||
}
|
||||
|
||||
parts := strings.SplitN(v, ";", 2)
|
||||
if len(parts) == 2 {
|
||||
tab.Server = parts[0]
|
||||
tab.Name = parts[1]
|
||||
}
|
||||
} else {
|
||||
parts := strings.Split(strings.Trim(path, "/"), "/")
|
||||
if len(parts) > 0 && len(parts) < 3 {
|
||||
if len(parts) == 2 {
|
||||
name, err := url.PathUnescape(parts[1])
|
||||
if err != nil {
|
||||
return tab, err
|
||||
}
|
||||
|
||||
tab.Name = name
|
||||
}
|
||||
|
||||
tab.Server = parts[0]
|
||||
}
|
||||
}
|
||||
return "", ""
|
||||
|
||||
return tab, nil
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ func easyjson7e607aefDecodeGithubComKhliengDispatchServer(in *jlexer.Lexer, out
|
||||
}
|
||||
in.Delim('{')
|
||||
for !in.IsDelim('}') {
|
||||
key := in.UnsafeString()
|
||||
key := in.UnsafeFieldName(false)
|
||||
in.WantColon()
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
@ -46,7 +46,7 @@ func easyjson7e607aefDecodeGithubComKhliengDispatchServer(in *jlexer.Lexer, out
|
||||
if out.Defaults == nil {
|
||||
out.Defaults = new(config.Defaults)
|
||||
}
|
||||
easyjson7e607aefDecodeGithubComKhliengDispatchConfig(in, &*out.Defaults)
|
||||
easyjson7e607aefDecodeGithubComKhliengDispatchConfig(in, out.Defaults)
|
||||
}
|
||||
case "servers":
|
||||
if in.IsNull() {
|
||||
@ -56,7 +56,7 @@ func easyjson7e607aefDecodeGithubComKhliengDispatchServer(in *jlexer.Lexer, out
|
||||
in.Delim('[')
|
||||
if out.Servers == nil {
|
||||
if !in.IsDelim(']') {
|
||||
out.Servers = make([]Server, 0, 1)
|
||||
out.Servers = make([]Server, 0, 0)
|
||||
} else {
|
||||
out.Servers = []Server{}
|
||||
}
|
||||
@ -97,13 +97,36 @@ func easyjson7e607aefDecodeGithubComKhliengDispatchServer(in *jlexer.Lexer, out
|
||||
if v2 == nil {
|
||||
v2 = new(storage.Channel)
|
||||
}
|
||||
easyjson7e607aefDecodeGithubComKhliengDispatchStorage(in, &*v2)
|
||||
easyjson7e607aefDecodeGithubComKhliengDispatchStorage(in, v2)
|
||||
}
|
||||
out.Channels = append(out.Channels, v2)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
}
|
||||
case "openDMs":
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
out.OpenDMs = nil
|
||||
} else {
|
||||
in.Delim('[')
|
||||
if out.OpenDMs == nil {
|
||||
if !in.IsDelim(']') {
|
||||
out.OpenDMs = make([]storage.Tab, 0, 2)
|
||||
} else {
|
||||
out.OpenDMs = []storage.Tab{}
|
||||
}
|
||||
} else {
|
||||
out.OpenDMs = (out.OpenDMs)[:0]
|
||||
}
|
||||
for !in.IsDelim(']') {
|
||||
var v3 storage.Tab
|
||||
easyjson7e607aefDecodeGithubComKhliengDispatchStorage1(in, &v3)
|
||||
out.OpenDMs = append(out.OpenDMs, v3)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
}
|
||||
case "hexIP":
|
||||
out.HexIP = bool(in.Bool())
|
||||
case "version":
|
||||
@ -162,12 +185,8 @@ func easyjson7e607aefEncodeGithubComKhliengDispatchServer(out *jwriter.Writer, i
|
||||
_ = first
|
||||
if in.Defaults != nil {
|
||||
const prefix string = ",\"defaults\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
easyjson7e607aefEncodeGithubComKhliengDispatchConfig(out, *in.Defaults)
|
||||
}
|
||||
if len(in.Servers) != 0 {
|
||||
@ -180,11 +199,11 @@ func easyjson7e607aefEncodeGithubComKhliengDispatchServer(out *jwriter.Writer, i
|
||||
}
|
||||
{
|
||||
out.RawByte('[')
|
||||
for v3, v4 := range in.Servers {
|
||||
if v3 > 0 {
|
||||
for v4, v5 := range in.Servers {
|
||||
if v4 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
out.Raw((v4).MarshalJSON())
|
||||
out.Raw((v5).MarshalJSON())
|
||||
}
|
||||
out.RawByte(']')
|
||||
}
|
||||
@ -199,19 +218,38 @@ func easyjson7e607aefEncodeGithubComKhliengDispatchServer(out *jwriter.Writer, i
|
||||
}
|
||||
{
|
||||
out.RawByte('[')
|
||||
for v5, v6 := range in.Channels {
|
||||
if v5 > 0 {
|
||||
for v6, v7 := range in.Channels {
|
||||
if v6 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
if v6 == nil {
|
||||
if v7 == nil {
|
||||
out.RawString("null")
|
||||
} else {
|
||||
easyjson7e607aefEncodeGithubComKhliengDispatchStorage(out, *v6)
|
||||
easyjson7e607aefEncodeGithubComKhliengDispatchStorage(out, *v7)
|
||||
}
|
||||
}
|
||||
out.RawByte(']')
|
||||
}
|
||||
}
|
||||
if len(in.OpenDMs) != 0 {
|
||||
const prefix string = ",\"openDMs\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
{
|
||||
out.RawByte('[')
|
||||
for v8, v9 := range in.OpenDMs {
|
||||
if v8 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
easyjson7e607aefEncodeGithubComKhliengDispatchStorage1(out, v9)
|
||||
}
|
||||
out.RawByte(']')
|
||||
}
|
||||
}
|
||||
if in.HexIP {
|
||||
const prefix string = ",\"hexIP\":"
|
||||
if first {
|
||||
@ -288,6 +326,61 @@ func (v *indexData) UnmarshalJSON(data []byte) error {
|
||||
func (v *indexData) UnmarshalEasyJSON(l *jlexer.Lexer) {
|
||||
easyjson7e607aefDecodeGithubComKhliengDispatchServer(l, v)
|
||||
}
|
||||
func easyjson7e607aefDecodeGithubComKhliengDispatchStorage1(in *jlexer.Lexer, out *storage.Tab) {
|
||||
isTopLevel := in.IsStart()
|
||||
if in.IsNull() {
|
||||
if isTopLevel {
|
||||
in.Consumed()
|
||||
}
|
||||
in.Skip()
|
||||
return
|
||||
}
|
||||
in.Delim('{')
|
||||
for !in.IsDelim('}') {
|
||||
key := in.UnsafeFieldName(false)
|
||||
in.WantColon()
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
in.WantComma()
|
||||
continue
|
||||
}
|
||||
switch key {
|
||||
case "server":
|
||||
out.Server = string(in.String())
|
||||
case "name":
|
||||
out.Name = string(in.String())
|
||||
default:
|
||||
in.SkipRecursive()
|
||||
}
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim('}')
|
||||
if isTopLevel {
|
||||
in.Consumed()
|
||||
}
|
||||
}
|
||||
func easyjson7e607aefEncodeGithubComKhliengDispatchStorage1(out *jwriter.Writer, in storage.Tab) {
|
||||
out.RawByte('{')
|
||||
first := true
|
||||
_ = first
|
||||
if in.Server != "" {
|
||||
const prefix string = ",\"server\":"
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
out.String(string(in.Server))
|
||||
}
|
||||
if in.Name != "" {
|
||||
const prefix string = ",\"name\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
out.String(string(in.Name))
|
||||
}
|
||||
out.RawByte('}')
|
||||
}
|
||||
func easyjson7e607aefDecodeGithubComKhliengDispatchStorage(in *jlexer.Lexer, out *storage.Channel) {
|
||||
isTopLevel := in.IsStart()
|
||||
if in.IsNull() {
|
||||
@ -299,7 +392,7 @@ func easyjson7e607aefDecodeGithubComKhliengDispatchStorage(in *jlexer.Lexer, out
|
||||
}
|
||||
in.Delim('{')
|
||||
for !in.IsDelim('}') {
|
||||
key := in.UnsafeString()
|
||||
key := in.UnsafeFieldName(false)
|
||||
in.WantColon()
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
@ -329,12 +422,8 @@ func easyjson7e607aefEncodeGithubComKhliengDispatchStorage(out *jwriter.Writer,
|
||||
_ = first
|
||||
if in.Server != "" {
|
||||
const prefix string = ",\"server\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
out.String(string(in.Server))
|
||||
}
|
||||
if in.Name != "" {
|
||||
@ -370,7 +459,7 @@ func easyjson7e607aefDecodeGithubComKhliengDispatchConfig(in *jlexer.Lexer, out
|
||||
}
|
||||
in.Delim('{')
|
||||
for !in.IsDelim('}') {
|
||||
key := in.UnsafeString()
|
||||
key := in.UnsafeFieldName(false)
|
||||
in.WantColon()
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
@ -400,9 +489,9 @@ func easyjson7e607aefDecodeGithubComKhliengDispatchConfig(in *jlexer.Lexer, out
|
||||
out.Channels = (out.Channels)[:0]
|
||||
}
|
||||
for !in.IsDelim(']') {
|
||||
var v7 string
|
||||
v7 = string(in.String())
|
||||
out.Channels = append(out.Channels, v7)
|
||||
var v10 string
|
||||
v10 = string(in.String())
|
||||
out.Channels = append(out.Channels, v10)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
@ -431,12 +520,8 @@ func easyjson7e607aefEncodeGithubComKhliengDispatchConfig(out *jwriter.Writer, i
|
||||
_ = first
|
||||
if in.Name != "" {
|
||||
const prefix string = ",\"name\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
out.String(string(in.Name))
|
||||
}
|
||||
if in.Host != "" {
|
||||
@ -469,11 +554,11 @@ func easyjson7e607aefEncodeGithubComKhliengDispatchConfig(out *jwriter.Writer, i
|
||||
}
|
||||
{
|
||||
out.RawByte('[')
|
||||
for v8, v9 := range in.Channels {
|
||||
if v8 > 0 {
|
||||
for v11, v12 := range in.Channels {
|
||||
if v11 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
out.String(string(v9))
|
||||
out.String(string(v12))
|
||||
}
|
||||
out.RawByte(']')
|
||||
}
|
||||
@ -531,7 +616,7 @@ func easyjson7e607aefDecodeGithubComKhliengDispatchServer1(in *jlexer.Lexer, out
|
||||
}
|
||||
in.Delim('{')
|
||||
for !in.IsDelim('}') {
|
||||
key := in.UnsafeString()
|
||||
key := in.UnsafeFieldName(false)
|
||||
in.WantColon()
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
@ -561,12 +646,8 @@ func easyjson7e607aefEncodeGithubComKhliengDispatchServer1(out *jwriter.Writer,
|
||||
_ = first
|
||||
if in.Tag != "" {
|
||||
const prefix string = ",\"tag\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
out.String(string(in.Tag))
|
||||
}
|
||||
if in.Commit != "" {
|
||||
@ -626,7 +707,7 @@ func easyjson7e607aefDecodeGithubComKhliengDispatchServer2(in *jlexer.Lexer, out
|
||||
}
|
||||
in.Delim('{')
|
||||
for !in.IsDelim('}') {
|
||||
key := in.UnsafeString()
|
||||
key := in.UnsafeFieldName(false)
|
||||
in.WantColon()
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
@ -656,9 +737,9 @@ func easyjson7e607aefDecodeGithubComKhliengDispatchServer2(in *jlexer.Lexer, out
|
||||
out.Channels = (out.Channels)[:0]
|
||||
}
|
||||
for !in.IsDelim(']') {
|
||||
var v10 string
|
||||
v10 = string(in.String())
|
||||
out.Channels = append(out.Channels, v10)
|
||||
var v13 string
|
||||
v13 = string(in.String())
|
||||
out.Channels = append(out.Channels, v13)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
@ -687,12 +768,8 @@ func easyjson7e607aefEncodeGithubComKhliengDispatchServer2(out *jwriter.Writer,
|
||||
_ = first
|
||||
if in.Name != "" {
|
||||
const prefix string = ",\"name\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
out.String(string(in.Name))
|
||||
}
|
||||
if in.Host != "" {
|
||||
@ -725,11 +802,11 @@ func easyjson7e607aefEncodeGithubComKhliengDispatchServer2(out *jwriter.Writer,
|
||||
}
|
||||
{
|
||||
out.RawByte('[')
|
||||
for v11, v12 := range in.Channels {
|
||||
if v11 > 0 {
|
||||
for v14, v15 := range in.Channels {
|
||||
if v14 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
out.String(string(v12))
|
||||
out.String(string(v15))
|
||||
}
|
||||
out.RawByte(']')
|
||||
}
|
||||
|
@ -1,47 +1,60 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/khlieng/dispatch/storage"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetTabFromPath(t *testing.T) {
|
||||
cases := []struct {
|
||||
input string
|
||||
expectedServer string
|
||||
expectedChannel string
|
||||
input *http.Request
|
||||
expectedTab Tab
|
||||
}{
|
||||
{
|
||||
"/chat.freenode.net/%23r%2Fstuff%2F/",
|
||||
"chat.freenode.net",
|
||||
"#r/stuff/",
|
||||
&http.Request{
|
||||
URL: &url.URL{Path: "/init"},
|
||||
Header: http.Header{"Referer": []string{"/chat.freenode.net/%23r%2Fstuff%2F"}},
|
||||
},
|
||||
Tab{storage.Tab{Server: "chat.freenode.net", Name: "#r/stuff/"}},
|
||||
}, {
|
||||
"/chat.freenode.net/%23r%2Fstuff%2F",
|
||||
"chat.freenode.net",
|
||||
"#r/stuff/",
|
||||
&http.Request{
|
||||
URL: &url.URL{Path: "/init"},
|
||||
Header: http.Header{"Referer": []string{"/chat.freenode.net/%23r%2Fstuff"}},
|
||||
},
|
||||
Tab{storage.Tab{Server: "chat.freenode.net", Name: "#r/stuff"}},
|
||||
}, {
|
||||
"/chat.freenode.net/%23r%2Fstuff",
|
||||
"chat.freenode.net",
|
||||
"#r/stuff",
|
||||
&http.Request{
|
||||
URL: &url.URL{Path: "/init"},
|
||||
Header: http.Header{"Referer": []string{"/chat.freenode.net/%23stuff"}},
|
||||
},
|
||||
Tab{storage.Tab{Server: "chat.freenode.net", Name: "#stuff"}},
|
||||
}, {
|
||||
"/chat.freenode.net/%23stuff",
|
||||
"chat.freenode.net",
|
||||
"#stuff",
|
||||
&http.Request{
|
||||
URL: &url.URL{Path: "/init"},
|
||||
Header: http.Header{"Referer": []string{"/chat.freenode.net/stuff"}},
|
||||
},
|
||||
Tab{storage.Tab{Server: "chat.freenode.net", Name: "stuff"}},
|
||||
}, {
|
||||
"/chat.freenode.net/%23stuff/cake",
|
||||
"",
|
||||
"",
|
||||
&http.Request{
|
||||
URL: &url.URL{Path: "/init"},
|
||||
Header: http.Header{"Referer": []string{"/data/chat.freenode.net/%23apples"}},
|
||||
},
|
||||
Tab{},
|
||||
}, {
|
||||
"/data/chat.freenode.net/%23apples",
|
||||
"chat.freenode.net",
|
||||
"#apples",
|
||||
&http.Request{
|
||||
URL: &url.URL{Path: "/ws/chat.freenode.net"},
|
||||
},
|
||||
Tab{storage.Tab{Server: "chat.freenode.net"}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
server, channel := getTabFromPath(tc.input)
|
||||
assert.Equal(t, tc.expectedServer, server)
|
||||
assert.Equal(t, tc.expectedChannel, channel)
|
||||
tab, err := tabFromRequest(tc.input)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, tc.expectedTab, tab)
|
||||
}
|
||||
}
|
||||
|
@ -169,17 +169,21 @@ func (i *ircHandler) message(msg *irc.Message) {
|
||||
From: msg.Nick,
|
||||
Content: msg.LastParam(),
|
||||
}
|
||||
target := msg.Params[0]
|
||||
|
||||
if msg.Params[0] == i.client.GetNick() {
|
||||
if target == i.client.GetNick() {
|
||||
i.state.sendJSON("pm", message)
|
||||
i.state.user.AddOpenDM(i.client.Host, message.From)
|
||||
|
||||
target = message.From
|
||||
} else {
|
||||
message.To = msg.Params[0]
|
||||
message.To = target
|
||||
i.state.sendJSON("message", message)
|
||||
}
|
||||
|
||||
if msg.Params[0] != "*" {
|
||||
if target != "*" {
|
||||
go i.state.user.LogMessage(message.ID,
|
||||
i.client.Host, msg.Nick, msg.Params[0], msg.LastParam())
|
||||
i.client.Host, msg.Nick, target, msg.LastParam())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,8 +212,8 @@ type ChannelSearch struct {
|
||||
}
|
||||
|
||||
type ChannelSearchResult struct {
|
||||
ChannelSearch
|
||||
Results []*storage.ChannelListItem
|
||||
Start int
|
||||
}
|
||||
|
||||
type ChannelForward struct {
|
||||
@ -221,3 +221,7 @@ type ChannelForward struct {
|
||||
Old string
|
||||
New string
|
||||
}
|
||||
|
||||
type Tab struct {
|
||||
storage.Tab
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,6 @@ package server
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@ -163,14 +162,8 @@ func (d *Dispatch) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if r.URL.Path == "/init" {
|
||||
referer, err := url.Parse(r.Header.Get("Referer"))
|
||||
if err != nil {
|
||||
fail(w, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
state := d.handleAuth(w, r, true, true)
|
||||
data := d.getIndexData(r, referer.EscapedPath(), state)
|
||||
data := d.getIndexData(r, state)
|
||||
|
||||
writeJSON(w, r, data)
|
||||
} else if strings.HasPrefix(r.URL.Path, "/ws") {
|
||||
|
@ -68,17 +68,15 @@ func (h *wsHandler) init(r *http.Request) {
|
||||
h.state.numIRC(), "IRC connections |",
|
||||
h.state.numWS(), "WebSocket connections")
|
||||
|
||||
tab, err := tabFromRequest(r)
|
||||
|
||||
channels, err := h.state.user.GetChannels()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
path := r.URL.EscapedPath()
|
||||
pathServer, pathChannel := getTabFromPath(path)
|
||||
cookieServer, cookieChannel := parseTabCookie(r, path[3:])
|
||||
|
||||
for _, channel := range channels {
|
||||
if (channel.Server == pathServer && channel.Name == pathChannel) ||
|
||||
(channel.Server == cookieServer && channel.Name == cookieChannel) {
|
||||
if channel.Server == tab.Server && channel.Name == tab.Name {
|
||||
// Userlist and messages for this channel gets embedded in the index page
|
||||
continue
|
||||
}
|
||||
@ -91,6 +89,19 @@ func (h *wsHandler) init(r *http.Request) {
|
||||
|
||||
h.state.sendLastMessages(channel.Server, channel.Name, 50)
|
||||
}
|
||||
|
||||
openDMs, err := h.state.user.GetOpenDMs()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
for _, openDM := range openDMs {
|
||||
if openDM.Server == tab.Server && openDM.Name == tab.Name {
|
||||
continue
|
||||
}
|
||||
|
||||
h.state.sendLastMessages(openDM.Server, openDM.Name, 50)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *wsHandler) connect(b []byte) {
|
||||
@ -295,8 +306,8 @@ func (h *wsHandler) channelSearch(b []byte) {
|
||||
}
|
||||
|
||||
h.state.sendJSON("channel_search", ChannelSearchResult{
|
||||
Results: index.SearchN(data.Q, data.Start, n),
|
||||
Start: data.Start,
|
||||
ChannelSearch: data,
|
||||
Results: index.SearchN(data.Q, data.Start, n),
|
||||
})
|
||||
}
|
||||
|
||||
@ -306,6 +317,21 @@ func (h *wsHandler) channelSearch(b []byte) {
|
||||
}
|
||||
}
|
||||
|
||||
func (h *wsHandler) openDM(b []byte) {
|
||||
var data Tab
|
||||
data.UnmarshalJSON(b)
|
||||
|
||||
h.state.sendLastMessages(data.Server, data.Name, 50)
|
||||
h.state.user.AddOpenDM(data.Server, data.Name)
|
||||
}
|
||||
|
||||
func (h *wsHandler) closeDM(b []byte) {
|
||||
var data Tab
|
||||
data.UnmarshalJSON(b)
|
||||
|
||||
h.state.user.RemoveOpenDM(data.Server, data.Name)
|
||||
}
|
||||
|
||||
func (h *wsHandler) initHandlers() {
|
||||
h.handlers = map[string]func([]byte){
|
||||
"connect": h.connect,
|
||||
@ -327,6 +353,8 @@ func (h *wsHandler) initHandlers() {
|
||||
"set_server_name": h.setServerName,
|
||||
"settings_set": h.setSettings,
|
||||
"channel_search": h.channelSearch,
|
||||
"open_dm": h.openDM,
|
||||
"close_dm": h.closeDM,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@ var (
|
||||
bucketUsers = []byte("Users")
|
||||
bucketServers = []byte("Servers")
|
||||
bucketChannels = []byte("Channels")
|
||||
bucketOpenDMs = []byte("OpenDMs")
|
||||
bucketMessages = []byte("Messages")
|
||||
bucketSessions = []byte("Sessions")
|
||||
)
|
||||
@ -34,6 +35,7 @@ func New(path string) (*BoltStore, error) {
|
||||
tx.CreateBucketIfNotExists(bucketUsers)
|
||||
tx.CreateBucketIfNotExists(bucketServers)
|
||||
tx.CreateBucketIfNotExists(bucketChannels)
|
||||
tx.CreateBucketIfNotExists(bucketOpenDMs)
|
||||
tx.CreateBucketIfNotExists(bucketMessages)
|
||||
tx.CreateBucketIfNotExists(bucketSessions)
|
||||
return nil
|
||||
@ -168,6 +170,13 @@ func (s *BoltStore) RemoveServer(user *storage.User, address string) error {
|
||||
b.Delete(k)
|
||||
}
|
||||
|
||||
b = tx.Bucket(bucketOpenDMs)
|
||||
c = b.Cursor()
|
||||
|
||||
for k, _ := c.Seek(serverID); bytes.HasPrefix(k, serverID); k, _ = c.Next() {
|
||||
b.Delete(k)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@ -246,6 +255,42 @@ func (s *BoltStore) RemoveChannel(user *storage.User, server, channel string) er
|
||||
})
|
||||
}
|
||||
|
||||
func (s *BoltStore) GetOpenDMs(user *storage.User) ([]storage.Tab, error) {
|
||||
var openDMs []storage.Tab
|
||||
|
||||
s.db.View(func(tx *bolt.Tx) error {
|
||||
c := tx.Bucket(bucketOpenDMs).Cursor()
|
||||
|
||||
for k, _ := c.Seek(user.IDBytes); bytes.HasPrefix(k, user.IDBytes); k, _ = c.Next() {
|
||||
tab := bytes.Split(k[8:], []byte{0})
|
||||
openDMs = append(openDMs, storage.Tab{
|
||||
Server: string(tab[0]),
|
||||
Name: string(tab[1]),
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return openDMs, nil
|
||||
}
|
||||
|
||||
func (s *BoltStore) AddOpenDM(user *storage.User, server, nick string) error {
|
||||
return s.db.Batch(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(bucketOpenDMs)
|
||||
|
||||
return b.Put(channelID(user, server, nick), nil)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *BoltStore) RemoveOpenDM(user *storage.User, server, nick string) error {
|
||||
return s.db.Batch(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(bucketOpenDMs)
|
||||
|
||||
return b.Delete(channelID(user, server, nick))
|
||||
})
|
||||
}
|
||||
|
||||
func (s *BoltStore) LogMessage(message *storage.Message) error {
|
||||
return s.db.Batch(func(tx *bolt.Tx) error {
|
||||
b, err := tx.Bucket(bucketMessages).CreateBucketIfNotExists([]byte(message.Server + ":" + message.To))
|
||||
|
@ -38,6 +38,10 @@ type Store interface {
|
||||
GetChannels(user *User) ([]*Channel, error)
|
||||
AddChannel(user *User, channel *Channel) error
|
||||
RemoveChannel(user *User, server, channel string) error
|
||||
|
||||
GetOpenDMs(user *User) ([]Tab, error)
|
||||
AddOpenDM(user *User, server, nick string) error
|
||||
RemoveOpenDM(user *User, server, nick string) error
|
||||
}
|
||||
|
||||
type SessionStore interface {
|
||||
|
@ -190,6 +190,23 @@ func (u *User) RemoveChannel(server, channel string) error {
|
||||
return u.store.RemoveChannel(u, server, channel)
|
||||
}
|
||||
|
||||
type Tab struct {
|
||||
Server string
|
||||
Name string
|
||||
}
|
||||
|
||||
func (u *User) GetOpenDMs() ([]Tab, error) {
|
||||
return u.store.GetOpenDMs(u)
|
||||
}
|
||||
|
||||
func (u *User) AddOpenDM(server, nick string) error {
|
||||
return u.store.AddOpenDM(u, server, nick)
|
||||
}
|
||||
|
||||
func (u *User) RemoveOpenDM(server, nick string) error {
|
||||
return u.store.RemoveOpenDM(u, server, nick)
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
ID string `json:"-" bleve:"-"`
|
||||
Server string `json:"-" bleve:"server"`
|
||||
|
@ -28,7 +28,7 @@ func easyjson9e1087fdDecodeGithubComKhliengDispatchStorage(in *jlexer.Lexer, out
|
||||
}
|
||||
in.Delim('{')
|
||||
for !in.IsDelim('}') {
|
||||
key := in.UnsafeString()
|
||||
key := in.UnsafeFieldName(false)
|
||||
in.WantColon()
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
@ -54,12 +54,8 @@ func easyjson9e1087fdEncodeGithubComKhliengDispatchStorage(out *jwriter.Writer,
|
||||
_ = first
|
||||
if in.ColoredNicks {
|
||||
const prefix string = ",\"coloredNicks\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
out.Bool(bool(in.ColoredNicks))
|
||||
}
|
||||
out.RawByte('}')
|
||||
|
@ -28,7 +28,7 @@ func TestUser(t *testing.T) {
|
||||
assert.Nil(t, err)
|
||||
|
||||
srv := &storage.Server{
|
||||
Name: "Freenode",
|
||||
Name: "freenode",
|
||||
Host: "irc.freenode.net",
|
||||
Nick: "test",
|
||||
}
|
||||
@ -80,6 +80,16 @@ func TestUser(t *testing.T) {
|
||||
channels, err = user.GetChannels()
|
||||
assert.Len(t, channels, 0)
|
||||
|
||||
user.AddOpenDM(srv.Host, "cake")
|
||||
openDMs, err := user.GetOpenDMs()
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, openDMs, 1)
|
||||
err = user.RemoveOpenDM(srv.Host, "cake")
|
||||
assert.Nil(t, err)
|
||||
openDMs, err = user.GetOpenDMs()
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, openDMs, 0)
|
||||
|
||||
settings := user.GetClientSettings()
|
||||
assert.NotNil(t, settings)
|
||||
assert.Equal(t, storage.DefaultClientSettings(), settings)
|
||||
|
14
vendor/github.com/golang/protobuf/proto/buffer.go
generated
vendored
14
vendor/github.com/golang/protobuf/proto/buffer.go
generated
vendored
@ -33,8 +33,8 @@ func SizeVarint(v uint64) int {
|
||||
return protowire.SizeVarint(v)
|
||||
}
|
||||
|
||||
// DecodeVarint parses a varint encoded integer from b, returning the
|
||||
// integer value and the length of the varint.
|
||||
// DecodeVarint parses a varint encoded integer from b,
|
||||
// returning the integer value and the length of the varint.
|
||||
// It returns (0, 0) if there is a parse error.
|
||||
func DecodeVarint(b []byte) (uint64, int) {
|
||||
v, n := protowire.ConsumeVarint(b)
|
||||
@ -112,9 +112,9 @@ func (b *Buffer) Marshal(m Message) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Unmarshal parses the wire-format message in the buffer and places the decoded results in m.
|
||||
//
|
||||
// Unlike proto.Unmarshal, this does not reset the message before starting to unmarshal.
|
||||
// Unmarshal parses the wire-format message in the buffer and
|
||||
// places the decoded results in m.
|
||||
// It does not reset m before unmarshaling.
|
||||
func (b *Buffer) Unmarshal(m Message) error {
|
||||
err := UnmarshalMerge(b.Unread(), m)
|
||||
b.idx = len(b.buf)
|
||||
@ -260,7 +260,7 @@ func (b *Buffer) DecodeStringBytes() (string, error) {
|
||||
}
|
||||
|
||||
// DecodeMessage consumes a length-prefixed message from the buffer.
|
||||
// It does not reset m.
|
||||
// It does not reset m before unmarshaling.
|
||||
func (b *Buffer) DecodeMessage(m Message) error {
|
||||
v, err := b.DecodeRawBytes(false)
|
||||
if err != nil {
|
||||
@ -272,7 +272,7 @@ func (b *Buffer) DecodeMessage(m Message) error {
|
||||
// DecodeGroup consumes a message group from the buffer.
|
||||
// It assumes that the start group marker has already been consumed and
|
||||
// consumes all bytes until (and including the end group marker).
|
||||
// It does not reset m.
|
||||
// It does not reset m before unmarshaling.
|
||||
func (b *Buffer) DecodeGroup(m Message) error {
|
||||
v, n, err := consumeGroup(b.buf[b.idx:])
|
||||
if err != nil {
|
||||
|
4
vendor/github.com/golang/protobuf/proto/extensions.go
generated
vendored
4
vendor/github.com/golang/protobuf/proto/extensions.go
generated
vendored
@ -68,7 +68,7 @@ func HasExtension(m Message, xt *ExtensionDesc) (has bool) {
|
||||
return has
|
||||
}
|
||||
|
||||
// ClearExtension removes the the exntesion field from m
|
||||
// ClearExtension removes the extension field from m
|
||||
// either as an explicitly populated field or as an unknown field.
|
||||
func ClearExtension(m Message, xt *ExtensionDesc) {
|
||||
mr := MessageReflect(m)
|
||||
@ -108,7 +108,7 @@ func ClearAllExtensions(m Message) {
|
||||
clearUnknown(mr, mr.Descriptor().ExtensionRanges())
|
||||
}
|
||||
|
||||
// GetExtension retrieves a proto2 extended field from pb.
|
||||
// GetExtension retrieves a proto2 extended field from m.
|
||||
//
|
||||
// If the descriptor is type complete (i.e., ExtensionDesc.ExtensionType is non-nil),
|
||||
// then GetExtension parses the encoded field and returns a Go value of the specified type.
|
||||
|
10
vendor/github.com/golang/protobuf/proto/registry.go
generated
vendored
10
vendor/github.com/golang/protobuf/proto/registry.go
generated
vendored
@ -29,7 +29,7 @@ var fileCache sync.Map // map[filePath]fileDescGZIP
|
||||
// RegisterFile is called from generated code to register the compressed
|
||||
// FileDescriptorProto with the file path for a proto source file.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalFiles.Register instead.
|
||||
// Deprecated: Use protoregistry.GlobalFiles.RegisterFile instead.
|
||||
func RegisterFile(s filePath, d fileDescGZIP) {
|
||||
// Decompress the descriptor.
|
||||
zr, err := gzip.NewReader(bytes.NewReader(d))
|
||||
@ -53,7 +53,7 @@ func RegisterFile(s filePath, d fileDescGZIP) {
|
||||
// FileDescriptor returns the compressed FileDescriptorProto given the file path
|
||||
// for a proto source file. It returns nil if not found.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalFiles.RangeFilesByPath instead.
|
||||
// Deprecated: Use protoregistry.GlobalFiles.FindFileByPath instead.
|
||||
func FileDescriptor(s filePath) fileDescGZIP {
|
||||
if v, ok := fileCache.Load(s); ok {
|
||||
return v.(fileDescGZIP)
|
||||
@ -98,7 +98,7 @@ var numFilesCache sync.Map // map[protoreflect.FullName]int
|
||||
// RegisterEnum is called from the generated code to register the mapping of
|
||||
// enum value names to enum numbers for the enum identified by s.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalTypes.Register instead.
|
||||
// Deprecated: Use protoregistry.GlobalTypes.RegisterEnum instead.
|
||||
func RegisterEnum(s enumName, _ enumsByNumber, m enumsByName) {
|
||||
if _, ok := enumCache.Load(s); ok {
|
||||
panic("proto: duplicate enum registered: " + s)
|
||||
@ -181,7 +181,7 @@ var messageTypeCache sync.Map // map[messageName]reflect.Type
|
||||
// RegisterType is called from generated code to register the message Go type
|
||||
// for a message of the given name.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalTypes.Register instead.
|
||||
// Deprecated: Use protoregistry.GlobalTypes.RegisterMessage instead.
|
||||
func RegisterType(m Message, s messageName) {
|
||||
mt := protoimpl.X.LegacyMessageTypeOf(m, protoreflect.FullName(s))
|
||||
if err := protoregistry.GlobalTypes.RegisterMessage(mt); err != nil {
|
||||
@ -280,7 +280,7 @@ func MessageName(m Message) messageName {
|
||||
// RegisterExtension is called from the generated code to register
|
||||
// the extension descriptor.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalTypes.Register instead.
|
||||
// Deprecated: Use protoregistry.GlobalTypes.RegisterExtension instead.
|
||||
func RegisterExtension(d *ExtensionDesc) {
|
||||
if err := protoregistry.GlobalTypes.RegisterExtension(d); err != nil {
|
||||
panic(err)
|
||||
|
8
vendor/github.com/golang/protobuf/proto/text_encode.go
generated
vendored
8
vendor/github.com/golang/protobuf/proto/text_encode.go
generated
vendored
@ -94,16 +94,16 @@ var (
|
||||
)
|
||||
|
||||
// MarshalText writes the proto text format of m to w.
|
||||
func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) }
|
||||
func MarshalText(w io.Writer, m Message) error { return defaultTextMarshaler.Marshal(w, m) }
|
||||
|
||||
// MarshalTextString returns a proto text formatted string of m.
|
||||
func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) }
|
||||
func MarshalTextString(m Message) string { return defaultTextMarshaler.Text(m) }
|
||||
|
||||
// CompactText writes the compact proto text format of m to w.
|
||||
func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) }
|
||||
func CompactText(w io.Writer, m Message) error { return compactTextMarshaler.Marshal(w, m) }
|
||||
|
||||
// CompactTextString returns a compact proto text formatted string of m.
|
||||
func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) }
|
||||
func CompactTextString(m Message) string { return compactTextMarshaler.Text(m) }
|
||||
|
||||
var (
|
||||
newline = []byte("\n")
|
||||
|
5
vendor/github.com/josharian/intern/README.md
generated
vendored
Normal file
5
vendor/github.com/josharian/intern/README.md
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
Docs: https://godoc.org/github.com/josharian/intern
|
||||
|
||||
See also [Go issue 5160](https://golang.org/issue/5160).
|
||||
|
||||
License: MIT
|
3
vendor/github.com/josharian/intern/go.mod
generated
vendored
Normal file
3
vendor/github.com/josharian/intern/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module github.com/josharian/intern
|
||||
|
||||
go 1.5
|
44
vendor/github.com/josharian/intern/intern.go
generated
vendored
Normal file
44
vendor/github.com/josharian/intern/intern.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
// Package intern interns strings.
|
||||
// Interning is best effort only.
|
||||
// Interned strings may be removed automatically
|
||||
// at any time without notification.
|
||||
// All functions may be called concurrently
|
||||
// with themselves and each other.
|
||||
package intern
|
||||
|
||||
import "sync"
|
||||
|
||||
var (
|
||||
pool sync.Pool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return make(map[string]string)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// String returns s, interned.
|
||||
func String(s string) string {
|
||||
m := pool.Get().(map[string]string)
|
||||
c, ok := m[s]
|
||||
if ok {
|
||||
pool.Put(m)
|
||||
return c
|
||||
}
|
||||
m[s] = s
|
||||
pool.Put(m)
|
||||
return s
|
||||
}
|
||||
|
||||
// Bytes returns b converted to a string, interned.
|
||||
func Bytes(b []byte) string {
|
||||
m := pool.Get().(map[string]string)
|
||||
c, ok := m[string(b)]
|
||||
if ok {
|
||||
pool.Put(m)
|
||||
return c
|
||||
}
|
||||
s := string(b)
|
||||
m[s] = s
|
||||
pool.Put(m)
|
||||
return s
|
||||
}
|
21
vendor/github.com/josharian/intern/license.md
generated
vendored
Normal file
21
vendor/github.com/josharian/intern/license.md
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Josh Bleecher Snyder
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
132
vendor/github.com/klauspost/cpuid/cpuid.go
generated
vendored
132
vendor/github.com/klauspost/cpuid/cpuid.go
generated
vendored
@ -10,7 +10,13 @@
|
||||
// Package home: https://github.com/klauspost/cpuid
|
||||
package cpuid
|
||||
|
||||
import "strings"
|
||||
import (
|
||||
"math"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// AMD refererence: https://www.amd.com/system/files/TechDocs/25481.pdf
|
||||
// and Processor Programming Reference (PPR)
|
||||
|
||||
// Vendor is a representation of a CPU vendor.
|
||||
type Vendor int
|
||||
@ -178,11 +184,12 @@ type CPUInfo struct {
|
||||
Family int // CPU family number
|
||||
Model int // CPU model number
|
||||
CacheLine int // Cache line size in bytes. Will be 0 if undetectable.
|
||||
Hz int64 // Clock speed, if known
|
||||
Cache struct {
|
||||
L1I int // L1 Instruction Cache (per core or shared). Will be -1 if undetected
|
||||
L1D int // L1 Data Cache (per core or shared). Will be -1 if undetected
|
||||
L2 int // L2 Cache (per core or shared). Will be -1 if undetected
|
||||
L3 int // L3 Instruction Cache (per core or shared). Will be -1 if undetected
|
||||
L3 int // L3 Cache (per core, per ccx or shared). Will be -1 if undetected
|
||||
}
|
||||
SGX SGXSupport
|
||||
maxFunc uint32
|
||||
@ -225,6 +232,7 @@ func Detect() {
|
||||
CPU.LogicalCores = logicalCores()
|
||||
CPU.PhysicalCores = physicalCores()
|
||||
CPU.VendorID = vendorID()
|
||||
CPU.Hz = hertz(CPU.BrandName)
|
||||
CPU.cacheSize()
|
||||
}
|
||||
|
||||
@ -601,6 +609,65 @@ func (c CPUInfo) LogicalCPU() int {
|
||||
return int(ebx >> 24)
|
||||
}
|
||||
|
||||
// hertz tries to compute the clock speed of the CPU. If leaf 15 is
|
||||
// supported, use it, otherwise parse the brand string. Yes, really.
|
||||
func hertz(model string) int64 {
|
||||
mfi := maxFunctionID()
|
||||
if mfi >= 0x15 {
|
||||
eax, ebx, ecx, _ := cpuid(0x15)
|
||||
if eax != 0 && ebx != 0 && ecx != 0 {
|
||||
return int64((int64(ecx) * int64(ebx)) / int64(eax))
|
||||
}
|
||||
}
|
||||
// computeHz determines the official rated speed of a CPU from its brand
|
||||
// string. This insanity is *actually the official documented way to do
|
||||
// this according to Intel*, prior to leaf 0x15 existing. The official
|
||||
// documentation only shows this working for exactly `x.xx` or `xxxx`
|
||||
// cases, e.g., `2.50GHz` or `1300MHz`; this parser will accept other
|
||||
// sizes.
|
||||
hz := strings.LastIndex(model, "Hz")
|
||||
if hz < 3 {
|
||||
return -1
|
||||
}
|
||||
var multiplier int64
|
||||
switch model[hz-1] {
|
||||
case 'M':
|
||||
multiplier = 1000 * 1000
|
||||
case 'G':
|
||||
multiplier = 1000 * 1000 * 1000
|
||||
case 'T':
|
||||
multiplier = 1000 * 1000 * 1000 * 1000
|
||||
}
|
||||
if multiplier == 0 {
|
||||
return -1
|
||||
}
|
||||
freq := int64(0)
|
||||
divisor := int64(0)
|
||||
decimalShift := int64(1)
|
||||
var i int
|
||||
for i = hz - 2; i >= 0 && model[i] != ' '; i-- {
|
||||
if model[i] >= '0' && model[i] <= '9' {
|
||||
freq += int64(model[i]-'0') * decimalShift
|
||||
decimalShift *= 10
|
||||
} else if model[i] == '.' {
|
||||
if divisor != 0 {
|
||||
return -1
|
||||
}
|
||||
divisor = decimalShift
|
||||
} else {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
// we didn't find a space
|
||||
if i < 0 {
|
||||
return -1
|
||||
}
|
||||
if divisor != 0 {
|
||||
return (freq * multiplier) / divisor
|
||||
}
|
||||
return freq * multiplier
|
||||
}
|
||||
|
||||
// VM Will return true if the cpu id indicates we are in
|
||||
// a virtual machine. This is only a hint, and will very likely
|
||||
// have many false negatives.
|
||||
@ -659,11 +726,14 @@ func brandName() string {
|
||||
|
||||
func threadsPerCore() int {
|
||||
mfi := maxFunctionID()
|
||||
if mfi < 0x4 || vendorID() != Intel {
|
||||
if mfi < 0x4 || (vendorID() != Intel && vendorID() != AMD) {
|
||||
return 1
|
||||
}
|
||||
|
||||
if mfi < 0xb {
|
||||
if vendorID() != Intel {
|
||||
return 1
|
||||
}
|
||||
_, b, _, d := cpuid(1)
|
||||
if (d & (1 << 28)) != 0 {
|
||||
// v will contain logical core count
|
||||
@ -727,6 +797,13 @@ func physicalCores() int {
|
||||
case Intel:
|
||||
return logicalCores() / threadsPerCore()
|
||||
case AMD, Hygon:
|
||||
lc := logicalCores()
|
||||
tpc := threadsPerCore()
|
||||
if lc > 0 && tpc > 0 {
|
||||
return lc / tpc
|
||||
}
|
||||
// The following is inaccurate on AMD EPYC 7742 64-Core Processor
|
||||
|
||||
if maxExtendedFunction() >= 0x80000008 {
|
||||
_, _, c, _ := cpuid(0x80000008)
|
||||
return int(c&0xff) + 1
|
||||
@ -837,6 +914,49 @@ func (c *CPUInfo) cacheSize() {
|
||||
}
|
||||
_, _, ecx, _ = cpuid(0x80000006)
|
||||
c.Cache.L2 = int(((ecx >> 16) & 0xFFFF) * 1024)
|
||||
|
||||
// CPUID Fn8000_001D_EAX_x[N:0] Cache Properties
|
||||
if maxExtendedFunction() < 0x8000001D {
|
||||
return
|
||||
}
|
||||
for i := uint32(0); i < math.MaxUint32; i++ {
|
||||
eax, ebx, ecx, _ := cpuidex(0x8000001D, i)
|
||||
|
||||
level := (eax >> 5) & 7
|
||||
cacheNumSets := ecx + 1
|
||||
cacheLineSize := 1 + (ebx & 2047)
|
||||
cachePhysPartitions := 1 + ((ebx >> 12) & 511)
|
||||
cacheNumWays := 1 + ((ebx >> 22) & 511)
|
||||
|
||||
typ := eax & 15
|
||||
size := int(cacheNumSets * cacheLineSize * cachePhysPartitions * cacheNumWays)
|
||||
if typ == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
switch level {
|
||||
case 1:
|
||||
switch typ {
|
||||
case 1:
|
||||
// Data cache
|
||||
c.Cache.L1D = size
|
||||
case 2:
|
||||
// Inst cache
|
||||
c.Cache.L1I = size
|
||||
default:
|
||||
if c.Cache.L1D < 0 {
|
||||
c.Cache.L1I = size
|
||||
}
|
||||
if c.Cache.L1I < 0 {
|
||||
c.Cache.L1I = size
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
c.Cache.L2 = size
|
||||
case 3:
|
||||
c.Cache.L3 = size
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
@ -954,7 +1074,11 @@ func support() Flags {
|
||||
rval |= HTT
|
||||
}
|
||||
}
|
||||
|
||||
if vend == AMD && (d&(1<<28)) != 0 && mfi >= 4 {
|
||||
if threadsPerCore() > 1 {
|
||||
rval |= HTT
|
||||
}
|
||||
}
|
||||
// Check XGETBV, OXSAVE and AVX bits
|
||||
if c&(1<<26) != 0 && c&(1<<27) != 0 && c&(1<<28) != 0 {
|
||||
// Check for OS support
|
||||
|
14
vendor/github.com/mailru/easyjson/Makefile
generated
vendored
14
vendor/github.com/mailru/easyjson/Makefile
generated
vendored
@ -20,6 +20,12 @@ generate: build
|
||||
./tests/reference_to_pointer.go \
|
||||
./tests/html.go \
|
||||
./tests/unknown_fields.go \
|
||||
./tests/type_declaration.go \
|
||||
./tests/members_escaped.go \
|
||||
./tests/members_unescaped.go \
|
||||
./tests/intern.go \
|
||||
./tests/nocopy.go \
|
||||
./tests/escaping.go \
|
||||
|
||||
bin/easyjson -all ./tests/data.go
|
||||
bin/easyjson -all ./tests/nothing.go
|
||||
@ -27,7 +33,7 @@ generate: build
|
||||
bin/easyjson -all ./tests/html.go
|
||||
bin/easyjson -snake_case ./tests/snake.go
|
||||
bin/easyjson -omit_empty ./tests/omitempty.go
|
||||
bin/easyjson -build_tags=use_easyjson ./benchmark/data.go
|
||||
bin/easyjson -build_tags=use_easyjson -disable_members_unescape ./benchmark/data.go
|
||||
bin/easyjson ./tests/nested_easy.go
|
||||
bin/easyjson ./tests/named_type.go
|
||||
bin/easyjson ./tests/custom_map_key_type.go
|
||||
@ -36,6 +42,12 @@ generate: build
|
||||
bin/easyjson ./tests/key_marshaler_map.go
|
||||
bin/easyjson -disallow_unknown_fields ./tests/disallow_unknown.go
|
||||
bin/easyjson ./tests/unknown_fields.go
|
||||
bin/easyjson ./tests/type_declaration.go
|
||||
bin/easyjson ./tests/members_escaped.go
|
||||
bin/easyjson -disable_members_unescape ./tests/members_unescaped.go
|
||||
bin/easyjson ./tests/intern.go
|
||||
bin/easyjson ./tests/nocopy.go
|
||||
bin/easyjson ./tests/escaping.go
|
||||
|
||||
test: generate
|
||||
go test \
|
||||
|
49
vendor/github.com/mailru/easyjson/README.md
generated
vendored
49
vendor/github.com/mailru/easyjson/README.md
generated
vendored
@ -35,6 +35,8 @@ Usage of easyjson:
|
||||
generate marshaler/unmarshalers for all structs in a file
|
||||
-build_tags string
|
||||
build tags to add to generated file
|
||||
-byte
|
||||
use simple bytes instead of Base64Bytes for slice of bytes
|
||||
-leave_temps
|
||||
do not delete temporary files
|
||||
-no_std_marshalers
|
||||
@ -55,6 +57,8 @@ Usage of easyjson:
|
||||
only generate stubs for marshaler/unmarshaler funcs
|
||||
-disallow_unknown_fields
|
||||
return error if some unknown field in json appeared
|
||||
-disable_members_unescape
|
||||
disable unescaping of \uXXXX string sequences in member names
|
||||
```
|
||||
|
||||
Using `-all` will generate marshalers/unmarshalers for all Go structs in the
|
||||
@ -76,10 +80,22 @@ Additional option notes:
|
||||
|
||||
* `-build_tags` will add the specified build tags to generated Go sources.
|
||||
|
||||
## Structure json tag options
|
||||
|
||||
Besides standart json tag options like 'omitempty' the following are supported:
|
||||
|
||||
* 'nocopy' - disables allocation and copying of string values, making them
|
||||
refer to original json buffer memory. This works great for short lived
|
||||
objects which are not hold in memory after decoding and immediate usage.
|
||||
Note if string requires unescaping it will be processed as normally.
|
||||
* 'intern' - string "interning" (deduplication) to save memory when the very
|
||||
same string dictionary values are often met all over the structure.
|
||||
See below for more details.
|
||||
|
||||
## Generated Marshaler/Unmarshaler Funcs
|
||||
|
||||
For Go struct types, easyjson generates the funcs `MarshalEasyJSON` /
|
||||
`UnmarshalEasyJSON` for marshaling/unmarshaling JSON. In turn, these satisify
|
||||
`UnmarshalEasyJSON` for marshaling/unmarshaling JSON. In turn, these satisfy
|
||||
the `easyjson.Marshaler` and `easyjson.Unmarshaler` interfaces and when used in
|
||||
conjunction with `easyjson.Marshal` / `easyjson.Unmarshal` avoid unnecessary
|
||||
reflection / type assertions during marshaling/unmarshaling to/from JSON for Go
|
||||
@ -102,17 +118,17 @@ utility funcs that are available.
|
||||
## Controlling easyjson Marshaling and Unmarshaling Behavior
|
||||
|
||||
Go types can provide their own `MarshalEasyJSON` and `UnmarshalEasyJSON` funcs
|
||||
that satisify the `easyjson.Marshaler` / `easyjson.Unmarshaler` interfaces.
|
||||
that satisfy the `easyjson.Marshaler` / `easyjson.Unmarshaler` interfaces.
|
||||
These will be used by `easyjson.Marshal` and `easyjson.Unmarshal` when defined
|
||||
for a Go type.
|
||||
|
||||
Go types can also satisify the `easyjson.Optional` interface, which allows the
|
||||
Go types can also satisfy the `easyjson.Optional` interface, which allows the
|
||||
type to define its own `omitempty` logic.
|
||||
|
||||
## Type Wrappers
|
||||
|
||||
easyjson provides additional type wrappers defined in the `easyjson/opt`
|
||||
package. These wrap the standard Go primitives and in turn satisify the
|
||||
package. These wrap the standard Go primitives and in turn satisfy the
|
||||
easyjson interfaces.
|
||||
|
||||
The `easyjson/opt` type wrappers are useful when needing to distinguish between
|
||||
@ -133,6 +149,27 @@ through a call to `buffer.Init()` prior to any marshaling or unmarshaling.
|
||||
Please see the [GoDoc listing](https://godoc.org/github.com/mailru/easyjson/buffer)
|
||||
for more information.
|
||||
|
||||
## String interning
|
||||
|
||||
During unmarshaling, `string` field values can be optionally
|
||||
[interned](https://en.wikipedia.org/wiki/String_interning) to reduce memory
|
||||
allocations and usage by deduplicating strings in memory, at the expense of slightly
|
||||
increased CPU usage.
|
||||
|
||||
This will work effectively only for `string` fields being decoded that have frequently
|
||||
the same value (e.g. if you have a string field that can only assume a small number
|
||||
of possible values).
|
||||
|
||||
To enable string interning, add the `intern` keyword tag to your `json` tag on `string`
|
||||
fields, e.g.:
|
||||
|
||||
```go
|
||||
type Foo struct {
|
||||
UUID string `json:"uuid"` // will not be interned during unmarshaling
|
||||
State string `json:"state,intern"` // will be interned during unmarshaling
|
||||
}
|
||||
```
|
||||
|
||||
## Issues, Notes, and Limitations
|
||||
|
||||
* easyjson is still early in its development. As such, there are likely to be
|
||||
@ -174,7 +211,7 @@ for more information.
|
||||
needs to be known prior to sending the data. Currently this is not possible
|
||||
with easyjson's architecture.
|
||||
|
||||
* easyjson parser and codegen based on reflection, so it wont works on `package main`
|
||||
* easyjson parser and codegen based on reflection, so it won't work on `package main`
|
||||
files, because they cant be imported by parser.
|
||||
|
||||
## Benchmarks
|
||||
@ -239,7 +276,7 @@ since the memory is not freed between marshaling operations.
|
||||
### easyjson vs 'ujson' python module
|
||||
|
||||
[ujson](https://github.com/esnme/ultrajson) is using C code for parsing, so it
|
||||
is interesting to see how plain golang compares to that. It is imporant to note
|
||||
is interesting to see how plain golang compares to that. It is important to note
|
||||
that the resulting object for python is slower to access, since the library
|
||||
parses JSON object into dictionaries.
|
||||
|
||||
|
72
vendor/github.com/mailru/easyjson/buffer/pool.go
generated
vendored
72
vendor/github.com/mailru/easyjson/buffer/pool.go
generated
vendored
@ -4,6 +4,7 @@ package buffer
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@ -52,14 +53,12 @@ func putBuf(buf []byte) {
|
||||
|
||||
// getBuf gets a chunk from reuse pool or creates a new one if reuse failed.
|
||||
func getBuf(size int) []byte {
|
||||
if size < config.PooledSize {
|
||||
return make([]byte, 0, size)
|
||||
}
|
||||
|
||||
if c := buffers[size]; c != nil {
|
||||
v := c.Get()
|
||||
if v != nil {
|
||||
return v.([]byte)
|
||||
if size >= config.PooledSize {
|
||||
if c := buffers[size]; c != nil {
|
||||
v := c.Get()
|
||||
if v != nil {
|
||||
return v.([]byte)
|
||||
}
|
||||
}
|
||||
}
|
||||
return make([]byte, 0, size)
|
||||
@ -78,9 +77,12 @@ type Buffer struct {
|
||||
// EnsureSpace makes sure that the current chunk contains at least s free bytes,
|
||||
// possibly creating a new chunk.
|
||||
func (b *Buffer) EnsureSpace(s int) {
|
||||
if cap(b.Buf)-len(b.Buf) >= s {
|
||||
return
|
||||
if cap(b.Buf)-len(b.Buf) < s {
|
||||
b.ensureSpaceSlow(s)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Buffer) ensureSpaceSlow(s int) {
|
||||
l := len(b.Buf)
|
||||
if l > 0 {
|
||||
if cap(b.toPool) != cap(b.Buf) {
|
||||
@ -105,18 +107,22 @@ func (b *Buffer) EnsureSpace(s int) {
|
||||
|
||||
// AppendByte appends a single byte to buffer.
|
||||
func (b *Buffer) AppendByte(data byte) {
|
||||
if cap(b.Buf) == len(b.Buf) { // EnsureSpace won't be inlined.
|
||||
b.EnsureSpace(1)
|
||||
}
|
||||
b.EnsureSpace(1)
|
||||
b.Buf = append(b.Buf, data)
|
||||
}
|
||||
|
||||
// AppendBytes appends a byte slice to buffer.
|
||||
func (b *Buffer) AppendBytes(data []byte) {
|
||||
if len(data) <= cap(b.Buf)-len(b.Buf) {
|
||||
b.Buf = append(b.Buf, data...) // fast path
|
||||
} else {
|
||||
b.appendBytesSlow(data)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Buffer) appendBytesSlow(data []byte) {
|
||||
for len(data) > 0 {
|
||||
if cap(b.Buf) == len(b.Buf) { // EnsureSpace won't be inlined.
|
||||
b.EnsureSpace(1)
|
||||
}
|
||||
b.EnsureSpace(1)
|
||||
|
||||
sz := cap(b.Buf) - len(b.Buf)
|
||||
if sz > len(data) {
|
||||
@ -128,12 +134,18 @@ func (b *Buffer) AppendBytes(data []byte) {
|
||||
}
|
||||
}
|
||||
|
||||
// AppendBytes appends a string to buffer.
|
||||
// AppendString appends a string to buffer.
|
||||
func (b *Buffer) AppendString(data string) {
|
||||
if len(data) <= cap(b.Buf)-len(b.Buf) {
|
||||
b.Buf = append(b.Buf, data...) // fast path
|
||||
} else {
|
||||
b.appendStringSlow(data)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Buffer) appendStringSlow(data string) {
|
||||
for len(data) > 0 {
|
||||
if cap(b.Buf) == len(b.Buf) { // EnsureSpace won't be inlined.
|
||||
b.EnsureSpace(1)
|
||||
}
|
||||
b.EnsureSpace(1)
|
||||
|
||||
sz := cap(b.Buf) - len(b.Buf)
|
||||
if sz > len(data) {
|
||||
@ -156,18 +168,14 @@ func (b *Buffer) Size() int {
|
||||
|
||||
// DumpTo outputs the contents of a buffer to a writer and resets the buffer.
|
||||
func (b *Buffer) DumpTo(w io.Writer) (written int, err error) {
|
||||
var n int
|
||||
for _, buf := range b.bufs {
|
||||
if err == nil {
|
||||
n, err = w.Write(buf)
|
||||
written += n
|
||||
}
|
||||
putBuf(buf)
|
||||
bufs := net.Buffers(b.bufs)
|
||||
if len(b.Buf) > 0 {
|
||||
bufs = append(bufs, b.Buf)
|
||||
}
|
||||
n, err := bufs.WriteTo(w)
|
||||
|
||||
if err == nil {
|
||||
n, err = w.Write(b.Buf)
|
||||
written += n
|
||||
for _, buf := range b.bufs {
|
||||
putBuf(buf)
|
||||
}
|
||||
putBuf(b.toPool)
|
||||
|
||||
@ -175,7 +183,7 @@ func (b *Buffer) DumpTo(w io.Writer) (written int, err error) {
|
||||
b.Buf = nil
|
||||
b.toPool = nil
|
||||
|
||||
return
|
||||
return int(n), err
|
||||
}
|
||||
|
||||
// BuildBytes creates a single byte slice with all the contents of the buffer. Data is
|
||||
@ -192,7 +200,7 @@ func (b *Buffer) BuildBytes(reuse ...[]byte) []byte {
|
||||
var ret []byte
|
||||
size := b.Size()
|
||||
|
||||
// If we got a buffer as argument and it is big enought, reuse it.
|
||||
// If we got a buffer as argument and it is big enough, reuse it.
|
||||
if len(reuse) == 1 && cap(reuse[0]) >= size {
|
||||
ret = reuse[0][:0]
|
||||
} else {
|
||||
|
2
vendor/github.com/mailru/easyjson/go.mod
generated
vendored
2
vendor/github.com/mailru/easyjson/go.mod
generated
vendored
@ -1,3 +1,5 @@
|
||||
module github.com/mailru/easyjson
|
||||
|
||||
go 1.12
|
||||
|
||||
require github.com/josharian/intern v1.0.0
|
||||
|
20
vendor/github.com/mailru/easyjson/helpers.go
generated
vendored
20
vendor/github.com/mailru/easyjson/helpers.go
generated
vendored
@ -6,6 +6,7 @@ import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
|
||||
"github.com/mailru/easyjson/jlexer"
|
||||
"github.com/mailru/easyjson/jwriter"
|
||||
@ -36,9 +37,17 @@ type UnknownsMarshaler interface {
|
||||
MarshalUnknowns(w *jwriter.Writer, first bool)
|
||||
}
|
||||
|
||||
func isNilInterface(i interface{}) bool {
|
||||
return (*[2]uintptr)(unsafe.Pointer(&i))[1] == 0
|
||||
}
|
||||
|
||||
// Marshal returns data as a single byte slice. Method is suboptimal as the data is likely to be copied
|
||||
// from a chain of smaller chunks.
|
||||
func Marshal(v Marshaler) ([]byte, error) {
|
||||
if isNilInterface(v) {
|
||||
return nullBytes, nil
|
||||
}
|
||||
|
||||
w := jwriter.Writer{}
|
||||
v.MarshalEasyJSON(&w)
|
||||
return w.BuildBytes()
|
||||
@ -46,6 +55,10 @@ func Marshal(v Marshaler) ([]byte, error) {
|
||||
|
||||
// MarshalToWriter marshals the data to an io.Writer.
|
||||
func MarshalToWriter(v Marshaler, w io.Writer) (written int, err error) {
|
||||
if isNilInterface(v) {
|
||||
return w.Write(nullBytes)
|
||||
}
|
||||
|
||||
jw := jwriter.Writer{}
|
||||
v.MarshalEasyJSON(&jw)
|
||||
return jw.DumpTo(w)
|
||||
@ -56,6 +69,13 @@ func MarshalToWriter(v Marshaler, w io.Writer) (written int, err error) {
|
||||
// false if an error occurred before any http.ResponseWriter methods were actually
|
||||
// invoked (in this case a 500 reply is possible).
|
||||
func MarshalToHTTPResponseWriter(v Marshaler, w http.ResponseWriter) (started bool, written int, err error) {
|
||||
if isNilInterface(v) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(nullBytes)))
|
||||
written, err = w.Write(nullBytes)
|
||||
return true, written, err
|
||||
}
|
||||
|
||||
jw := jwriter.Writer{}
|
||||
v.MarshalEasyJSON(&jw)
|
||||
if jw.Error != nil {
|
||||
|
216
vendor/github.com/mailru/easyjson/jlexer/lexer.go
generated
vendored
216
vendor/github.com/mailru/easyjson/jlexer/lexer.go
generated
vendored
@ -5,6 +5,7 @@
|
||||
package jlexer
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
@ -14,6 +15,8 @@ import (
|
||||
"unicode"
|
||||
"unicode/utf16"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/josharian/intern"
|
||||
)
|
||||
|
||||
// tokenKind determines type of a token.
|
||||
@ -32,9 +35,10 @@ const (
|
||||
type token struct {
|
||||
kind tokenKind // Type of a token.
|
||||
|
||||
boolValue bool // Value if a boolean literal token.
|
||||
byteValue []byte // Raw value of a token.
|
||||
delimValue byte
|
||||
boolValue bool // Value if a boolean literal token.
|
||||
byteValueCloned bool // true if byteValue was allocated and does not refer to original json body
|
||||
byteValue []byte // Raw value of a token.
|
||||
delimValue byte
|
||||
}
|
||||
|
||||
// Lexer is a JSON lexer: it iterates over JSON tokens in a byte slice.
|
||||
@ -240,23 +244,65 @@ func (r *Lexer) fetchNumber() {
|
||||
|
||||
// findStringLen tries to scan into the string literal for ending quote char to determine required size.
|
||||
// The size will be exact if no escapes are present and may be inexact if there are escaped chars.
|
||||
func findStringLen(data []byte) (isValid, hasEscapes bool, length int) {
|
||||
delta := 0
|
||||
|
||||
for i := 0; i < len(data); i++ {
|
||||
switch data[i] {
|
||||
case '\\':
|
||||
i++
|
||||
delta++
|
||||
if i < len(data) && data[i] == 'u' {
|
||||
delta++
|
||||
}
|
||||
case '"':
|
||||
return true, (delta > 0), (i - delta)
|
||||
func findStringLen(data []byte) (isValid bool, length int) {
|
||||
for {
|
||||
idx := bytes.IndexByte(data, '"')
|
||||
if idx == -1 {
|
||||
return false, len(data)
|
||||
}
|
||||
if idx == 0 || (idx > 0 && data[idx-1] != '\\') {
|
||||
return true, length + idx
|
||||
}
|
||||
|
||||
// count \\\\\\\ sequences. even number of slashes means quote is not really escaped
|
||||
cnt := 1
|
||||
for idx-cnt-1 >= 0 && data[idx-cnt-1] == '\\' {
|
||||
cnt++
|
||||
}
|
||||
if cnt%2 == 0 {
|
||||
return true, length + idx
|
||||
}
|
||||
|
||||
length += idx + 1
|
||||
data = data[idx+1:]
|
||||
}
|
||||
}
|
||||
|
||||
// unescapeStringToken performs unescaping of string token.
|
||||
// if no escaping is needed, original string is returned, otherwise - a new one allocated
|
||||
func (r *Lexer) unescapeStringToken() (err error) {
|
||||
data := r.token.byteValue
|
||||
var unescapedData []byte
|
||||
|
||||
for {
|
||||
i := bytes.IndexByte(data, '\\')
|
||||
if i == -1 {
|
||||
break
|
||||
}
|
||||
|
||||
escapedRune, escapedBytes, err := decodeEscape(data[i:])
|
||||
if err != nil {
|
||||
r.errParse(err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
if unescapedData == nil {
|
||||
unescapedData = make([]byte, 0, len(r.token.byteValue))
|
||||
}
|
||||
|
||||
var d [4]byte
|
||||
s := utf8.EncodeRune(d[:], escapedRune)
|
||||
unescapedData = append(unescapedData, data[:i]...)
|
||||
unescapedData = append(unescapedData, d[:s]...)
|
||||
|
||||
data = data[i+escapedBytes:]
|
||||
}
|
||||
|
||||
return false, false, len(data)
|
||||
if unescapedData != nil {
|
||||
r.token.byteValue = append(unescapedData, data...)
|
||||
r.token.byteValueCloned = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// getu4 decodes \uXXXX from the beginning of s, returning the hex value,
|
||||
@ -286,36 +332,30 @@ func getu4(s []byte) rune {
|
||||
return val
|
||||
}
|
||||
|
||||
// processEscape processes a single escape sequence and returns number of bytes processed.
|
||||
func (r *Lexer) processEscape(data []byte) (int, error) {
|
||||
// decodeEscape processes a single escape sequence and returns number of bytes processed.
|
||||
func decodeEscape(data []byte) (decoded rune, bytesProcessed int, err error) {
|
||||
if len(data) < 2 {
|
||||
return 0, fmt.Errorf("syntax error at %v", string(data))
|
||||
return 0, 0, errors.New("incorrect escape symbol \\ at the end of token")
|
||||
}
|
||||
|
||||
c := data[1]
|
||||
switch c {
|
||||
case '"', '/', '\\':
|
||||
r.token.byteValue = append(r.token.byteValue, c)
|
||||
return 2, nil
|
||||
return rune(c), 2, nil
|
||||
case 'b':
|
||||
r.token.byteValue = append(r.token.byteValue, '\b')
|
||||
return 2, nil
|
||||
return '\b', 2, nil
|
||||
case 'f':
|
||||
r.token.byteValue = append(r.token.byteValue, '\f')
|
||||
return 2, nil
|
||||
return '\f', 2, nil
|
||||
case 'n':
|
||||
r.token.byteValue = append(r.token.byteValue, '\n')
|
||||
return 2, nil
|
||||
return '\n', 2, nil
|
||||
case 'r':
|
||||
r.token.byteValue = append(r.token.byteValue, '\r')
|
||||
return 2, nil
|
||||
return '\r', 2, nil
|
||||
case 't':
|
||||
r.token.byteValue = append(r.token.byteValue, '\t')
|
||||
return 2, nil
|
||||
return '\t', 2, nil
|
||||
case 'u':
|
||||
rr := getu4(data)
|
||||
if rr < 0 {
|
||||
return 0, errors.New("syntax error")
|
||||
return 0, 0, errors.New("incorrectly escaped \\uXXXX sequence")
|
||||
}
|
||||
|
||||
read := 6
|
||||
@ -328,13 +368,10 @@ func (r *Lexer) processEscape(data []byte) (int, error) {
|
||||
rr = unicode.ReplacementChar
|
||||
}
|
||||
}
|
||||
var d [4]byte
|
||||
s := utf8.EncodeRune(d[:], rr)
|
||||
r.token.byteValue = append(r.token.byteValue, d[:s]...)
|
||||
return read, nil
|
||||
return rr, read, nil
|
||||
}
|
||||
|
||||
return 0, errors.New("syntax error")
|
||||
return 0, 0, errors.New("incorrectly escaped bytes")
|
||||
}
|
||||
|
||||
// fetchString scans a string literal token.
|
||||
@ -342,43 +379,14 @@ func (r *Lexer) fetchString() {
|
||||
r.pos++
|
||||
data := r.Data[r.pos:]
|
||||
|
||||
isValid, hasEscapes, length := findStringLen(data)
|
||||
isValid, length := findStringLen(data)
|
||||
if !isValid {
|
||||
r.pos += length
|
||||
r.errParse("unterminated string literal")
|
||||
return
|
||||
}
|
||||
if !hasEscapes {
|
||||
r.token.byteValue = data[:length]
|
||||
r.pos += length + 1
|
||||
return
|
||||
}
|
||||
|
||||
r.token.byteValue = make([]byte, 0, length)
|
||||
p := 0
|
||||
for i := 0; i < len(data); {
|
||||
switch data[i] {
|
||||
case '"':
|
||||
r.pos += i + 1
|
||||
r.token.byteValue = append(r.token.byteValue, data[p:i]...)
|
||||
i++
|
||||
return
|
||||
|
||||
case '\\':
|
||||
r.token.byteValue = append(r.token.byteValue, data[p:i]...)
|
||||
off, err := r.processEscape(data[i:])
|
||||
if err != nil {
|
||||
r.errParse(err.Error())
|
||||
return
|
||||
}
|
||||
i += off
|
||||
p = i
|
||||
|
||||
default:
|
||||
i++
|
||||
}
|
||||
}
|
||||
r.errParse("unterminated string literal")
|
||||
r.token.byteValue = data[:length]
|
||||
r.pos += length + 1 // skip closing '"' as well
|
||||
}
|
||||
|
||||
// scanToken scans the next token if no token is currently available in the lexer.
|
||||
@ -602,7 +610,7 @@ func (r *Lexer) Consumed() {
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Lexer) unsafeString() (string, []byte) {
|
||||
func (r *Lexer) unsafeString(skipUnescape bool) (string, []byte) {
|
||||
if r.token.kind == tokenUndef && r.Ok() {
|
||||
r.FetchToken()
|
||||
}
|
||||
@ -610,6 +618,13 @@ func (r *Lexer) unsafeString() (string, []byte) {
|
||||
r.errInvalidToken("string")
|
||||
return "", nil
|
||||
}
|
||||
if !skipUnescape {
|
||||
if err := r.unescapeStringToken(); err != nil {
|
||||
r.errInvalidToken("string")
|
||||
return "", nil
|
||||
}
|
||||
}
|
||||
|
||||
bytes := r.token.byteValue
|
||||
ret := bytesToStr(r.token.byteValue)
|
||||
r.consume()
|
||||
@ -621,13 +636,19 @@ func (r *Lexer) unsafeString() (string, []byte) {
|
||||
// Warning: returned string may point to the input buffer, so the string should not outlive
|
||||
// the input buffer. Intended pattern of usage is as an argument to a switch statement.
|
||||
func (r *Lexer) UnsafeString() string {
|
||||
ret, _ := r.unsafeString()
|
||||
ret, _ := r.unsafeString(false)
|
||||
return ret
|
||||
}
|
||||
|
||||
// UnsafeBytes returns the byte slice if the token is a string literal.
|
||||
func (r *Lexer) UnsafeBytes() []byte {
|
||||
_, ret := r.unsafeString()
|
||||
_, ret := r.unsafeString(false)
|
||||
return ret
|
||||
}
|
||||
|
||||
// UnsafeFieldName returns current member name string token
|
||||
func (r *Lexer) UnsafeFieldName(skipUnescape bool) string {
|
||||
ret, _ := r.unsafeString(skipUnescape)
|
||||
return ret
|
||||
}
|
||||
|
||||
@ -640,7 +661,34 @@ func (r *Lexer) String() string {
|
||||
r.errInvalidToken("string")
|
||||
return ""
|
||||
}
|
||||
ret := string(r.token.byteValue)
|
||||
if err := r.unescapeStringToken(); err != nil {
|
||||
r.errInvalidToken("string")
|
||||
return ""
|
||||
}
|
||||
var ret string
|
||||
if r.token.byteValueCloned {
|
||||
ret = bytesToStr(r.token.byteValue)
|
||||
} else {
|
||||
ret = string(r.token.byteValue)
|
||||
}
|
||||
r.consume()
|
||||
return ret
|
||||
}
|
||||
|
||||
// StringIntern reads a string literal, and performs string interning on it.
|
||||
func (r *Lexer) StringIntern() string {
|
||||
if r.token.kind == tokenUndef && r.Ok() {
|
||||
r.FetchToken()
|
||||
}
|
||||
if !r.Ok() || r.token.kind != tokenString {
|
||||
r.errInvalidToken("string")
|
||||
return ""
|
||||
}
|
||||
if err := r.unescapeStringToken(); err != nil {
|
||||
r.errInvalidToken("string")
|
||||
return ""
|
||||
}
|
||||
ret := intern.Bytes(r.token.byteValue)
|
||||
r.consume()
|
||||
return ret
|
||||
}
|
||||
@ -839,7 +887,7 @@ func (r *Lexer) Int() int {
|
||||
}
|
||||
|
||||
func (r *Lexer) Uint8Str() uint8 {
|
||||
s, b := r.unsafeString()
|
||||
s, b := r.unsafeString(false)
|
||||
if !r.Ok() {
|
||||
return 0
|
||||
}
|
||||
@ -856,7 +904,7 @@ func (r *Lexer) Uint8Str() uint8 {
|
||||
}
|
||||
|
||||
func (r *Lexer) Uint16Str() uint16 {
|
||||
s, b := r.unsafeString()
|
||||
s, b := r.unsafeString(false)
|
||||
if !r.Ok() {
|
||||
return 0
|
||||
}
|
||||
@ -873,7 +921,7 @@ func (r *Lexer) Uint16Str() uint16 {
|
||||
}
|
||||
|
||||
func (r *Lexer) Uint32Str() uint32 {
|
||||
s, b := r.unsafeString()
|
||||
s, b := r.unsafeString(false)
|
||||
if !r.Ok() {
|
||||
return 0
|
||||
}
|
||||
@ -890,7 +938,7 @@ func (r *Lexer) Uint32Str() uint32 {
|
||||
}
|
||||
|
||||
func (r *Lexer) Uint64Str() uint64 {
|
||||
s, b := r.unsafeString()
|
||||
s, b := r.unsafeString(false)
|
||||
if !r.Ok() {
|
||||
return 0
|
||||
}
|
||||
@ -915,7 +963,7 @@ func (r *Lexer) UintptrStr() uintptr {
|
||||
}
|
||||
|
||||
func (r *Lexer) Int8Str() int8 {
|
||||
s, b := r.unsafeString()
|
||||
s, b := r.unsafeString(false)
|
||||
if !r.Ok() {
|
||||
return 0
|
||||
}
|
||||
@ -932,7 +980,7 @@ func (r *Lexer) Int8Str() int8 {
|
||||
}
|
||||
|
||||
func (r *Lexer) Int16Str() int16 {
|
||||
s, b := r.unsafeString()
|
||||
s, b := r.unsafeString(false)
|
||||
if !r.Ok() {
|
||||
return 0
|
||||
}
|
||||
@ -949,7 +997,7 @@ func (r *Lexer) Int16Str() int16 {
|
||||
}
|
||||
|
||||
func (r *Lexer) Int32Str() int32 {
|
||||
s, b := r.unsafeString()
|
||||
s, b := r.unsafeString(false)
|
||||
if !r.Ok() {
|
||||
return 0
|
||||
}
|
||||
@ -966,7 +1014,7 @@ func (r *Lexer) Int32Str() int32 {
|
||||
}
|
||||
|
||||
func (r *Lexer) Int64Str() int64 {
|
||||
s, b := r.unsafeString()
|
||||
s, b := r.unsafeString(false)
|
||||
if !r.Ok() {
|
||||
return 0
|
||||
}
|
||||
@ -1004,7 +1052,7 @@ func (r *Lexer) Float32() float32 {
|
||||
}
|
||||
|
||||
func (r *Lexer) Float32Str() float32 {
|
||||
s, b := r.unsafeString()
|
||||
s, b := r.unsafeString(false)
|
||||
if !r.Ok() {
|
||||
return 0
|
||||
}
|
||||
@ -1037,7 +1085,7 @@ func (r *Lexer) Float64() float64 {
|
||||
}
|
||||
|
||||
func (r *Lexer) Float64Str() float64 {
|
||||
s, b := r.unsafeString()
|
||||
s, b := r.unsafeString(false)
|
||||
if !r.Ok() {
|
||||
return 0
|
||||
}
|
||||
|
6
vendor/github.com/mailru/easyjson/jwriter/writer.go
generated
vendored
6
vendor/github.com/mailru/easyjson/jwriter/writer.go
generated
vendored
@ -297,11 +297,9 @@ func (w *Writer) String(s string) {
|
||||
|
||||
p := 0 // last non-escape symbol
|
||||
|
||||
var escapeTable [128]bool
|
||||
escapeTable := &htmlEscapeTable
|
||||
if w.NoEscapeHTML {
|
||||
escapeTable = htmlNoEscapeTable
|
||||
} else {
|
||||
escapeTable = htmlEscapeTable
|
||||
escapeTable = &htmlNoEscapeTable
|
||||
}
|
||||
|
||||
for i := 0; i < len(s); {
|
||||
|
10
vendor/github.com/mailru/easyjson/unknown_fields.go
generated
vendored
10
vendor/github.com/mailru/easyjson/unknown_fields.go
generated
vendored
@ -1,8 +1,6 @@
|
||||
package easyjson
|
||||
|
||||
import (
|
||||
json "encoding/json"
|
||||
|
||||
jlexer "github.com/mailru/easyjson/jlexer"
|
||||
"github.com/mailru/easyjson/jwriter"
|
||||
)
|
||||
@ -10,14 +8,14 @@ import (
|
||||
// UnknownFieldsProxy implemets UnknownsUnmarshaler and UnknownsMarshaler
|
||||
// use it as embedded field in your structure to parse and then serialize unknown struct fields
|
||||
type UnknownFieldsProxy struct {
|
||||
unknownFields map[string]interface{}
|
||||
unknownFields map[string][]byte
|
||||
}
|
||||
|
||||
func (s *UnknownFieldsProxy) UnmarshalUnknown(in *jlexer.Lexer, key string) {
|
||||
if s.unknownFields == nil {
|
||||
s.unknownFields = make(map[string]interface{}, 1)
|
||||
s.unknownFields = make(map[string][]byte, 1)
|
||||
}
|
||||
s.unknownFields[key] = in.Interface()
|
||||
s.unknownFields[key] = in.Raw()
|
||||
}
|
||||
|
||||
func (s UnknownFieldsProxy) MarshalUnknowns(out *jwriter.Writer, first bool) {
|
||||
@ -29,6 +27,6 @@ func (s UnknownFieldsProxy) MarshalUnknowns(out *jwriter.Writer, first bool) {
|
||||
}
|
||||
out.String(string(key))
|
||||
out.RawByte(':')
|
||||
out.Raw(json.Marshal(val))
|
||||
out.Raw(val, nil)
|
||||
}
|
||||
}
|
||||
|
5
vendor/golang.org/x/net/ipv4/header.go
generated
vendored
5
vendor/golang.org/x/net/ipv4/header.go
generated
vendored
@ -14,9 +14,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
Version = 4 // protocol version
|
||||
HeaderLen = 20 // header length without extension headers
|
||||
maxHeaderLen = 60 // sensible default, revisit if later RFCs define new usage of version and header length fields
|
||||
Version = 4 // protocol version
|
||||
HeaderLen = 20 // header length without extension headers
|
||||
)
|
||||
|
||||
type HeaderFlags int
|
||||
|
30
vendor/golang.org/x/sys/internal/unsafeheader/unsafeheader.go
generated
vendored
Normal file
30
vendor/golang.org/x/sys/internal/unsafeheader/unsafeheader.go
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package unsafeheader contains header declarations for the Go runtime's
|
||||
// slice and string implementations.
|
||||
//
|
||||
// This package allows x/sys to use types equivalent to
|
||||
// reflect.SliceHeader and reflect.StringHeader without introducing
|
||||
// a dependency on the (relatively heavy) "reflect" package.
|
||||
package unsafeheader
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Slice is the runtime representation of a slice.
|
||||
// It cannot be used safely or portably and its representation may change in a later release.
|
||||
type Slice struct {
|
||||
Data unsafe.Pointer
|
||||
Len int
|
||||
Cap int
|
||||
}
|
||||
|
||||
// String is the runtime representation of a string.
|
||||
// It cannot be used safely or portably and its representation may change in a later release.
|
||||
type String struct {
|
||||
Data unsafe.Pointer
|
||||
Len int
|
||||
}
|
3
vendor/golang.org/x/sys/unix/mkerrors.sh
generated
vendored
3
vendor/golang.org/x/sys/unix/mkerrors.sh
generated
vendored
@ -187,6 +187,7 @@ struct ltchars {
|
||||
#include <sys/select.h>
|
||||
#include <sys/signalfd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/timerfd.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/xattr.h>
|
||||
#include <linux/bpf.h>
|
||||
@ -480,7 +481,7 @@ ccflags="$@"
|
||||
$2 ~ /^(MS|MNT|UMOUNT)_/ ||
|
||||
$2 ~ /^NS_GET_/ ||
|
||||
$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
|
||||
$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT)_/ ||
|
||||
$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT|TFD)_/ ||
|
||||
$2 ~ /^KEXEC_/ ||
|
||||
$2 ~ /^LINUX_REBOOT_CMD_/ ||
|
||||
$2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
|
||||
|
21
vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go
generated
vendored
21
vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go
generated
vendored
@ -6,7 +6,11 @@
|
||||
|
||||
package unix
|
||||
|
||||
import "unsafe"
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/internal/unsafeheader"
|
||||
)
|
||||
|
||||
//sys closedir(dir uintptr) (err error)
|
||||
//sys readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno)
|
||||
@ -71,6 +75,7 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
|
||||
cnt++
|
||||
continue
|
||||
}
|
||||
|
||||
reclen := int(entry.Reclen)
|
||||
if reclen > len(buf) {
|
||||
// Not enough room. Return for now.
|
||||
@ -79,13 +84,15 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
|
||||
// restarting is O(n^2) in the length of the directory. Oh well.
|
||||
break
|
||||
}
|
||||
|
||||
// Copy entry into return buffer.
|
||||
s := struct {
|
||||
ptr unsafe.Pointer
|
||||
siz int
|
||||
cap int
|
||||
}{ptr: unsafe.Pointer(&entry), siz: reclen, cap: reclen}
|
||||
copy(buf, *(*[]byte)(unsafe.Pointer(&s)))
|
||||
var s []byte
|
||||
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&s))
|
||||
hdr.Data = unsafe.Pointer(&entry)
|
||||
hdr.Cap = reclen
|
||||
hdr.Len = reclen
|
||||
copy(buf, s)
|
||||
|
||||
buf = buf[reclen:]
|
||||
n += reclen
|
||||
cnt++
|
||||
|
13
vendor/golang.org/x/sys/unix/syscall_linux.go
generated
vendored
13
vendor/golang.org/x/sys/unix/syscall_linux.go
generated
vendored
@ -1633,6 +1633,15 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||
//sys CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error)
|
||||
//sys DeleteModule(name string, flags int) (err error)
|
||||
//sys Dup(oldfd int) (fd int, err error)
|
||||
|
||||
func Dup2(oldfd, newfd int) error {
|
||||
// Android O and newer blocks dup2; riscv and arm64 don't implement dup2.
|
||||
if runtime.GOOS == "android" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "arm64" {
|
||||
return Dup3(oldfd, newfd, 0)
|
||||
}
|
||||
return dup2(oldfd, newfd)
|
||||
}
|
||||
|
||||
//sys Dup3(oldfd int, newfd int, flags int) (err error)
|
||||
//sysnb EpollCreate1(flag int) (fd int, err error)
|
||||
//sysnb EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error)
|
||||
@ -1757,6 +1766,9 @@ func Signalfd(fd int, sigmask *Sigset_t, flags int) (newfd int, err error) {
|
||||
//sys Syncfs(fd int) (err error)
|
||||
//sysnb Sysinfo(info *Sysinfo_t) (err error)
|
||||
//sys Tee(rfd int, wfd int, len int, flags int) (n int64, err error)
|
||||
//sysnb TimerfdCreate(clockid int, flags int) (fd int, err error)
|
||||
//sysnb TimerfdGettime(fd int, currValue *ItimerSpec) (err error)
|
||||
//sysnb TimerfdSettime(fd int, flags int, newValue *ItimerSpec, oldValue *ItimerSpec) (err error)
|
||||
//sysnb Tgkill(tgid int, tid int, sig syscall.Signal) (err error)
|
||||
//sysnb Times(tms *Tms) (ticks uintptr, err error)
|
||||
//sysnb Umask(mask int) (oldmask int)
|
||||
@ -2178,7 +2190,6 @@ func Klogset(typ int, arg int) (err error) {
|
||||
// TimerGetoverrun
|
||||
// TimerGettime
|
||||
// TimerSettime
|
||||
// Timerfd
|
||||
// Tkill (obsolete)
|
||||
// Tuxcall
|
||||
// Umount2
|
||||
|
2
vendor/golang.org/x/sys/unix/syscall_linux_386.go
generated
vendored
2
vendor/golang.org/x/sys/unix/syscall_linux_386.go
generated
vendored
@ -49,7 +49,7 @@ func Pipe2(p []int, flags int) (err error) {
|
||||
|
||||
// 64-bit file system and 32-bit uid calls
|
||||
// (386 default is 32-bit file system and 16-bit uid).
|
||||
//sys Dup2(oldfd int, newfd int) (err error)
|
||||
//sys dup2(oldfd int, newfd int) (err error)
|
||||
//sysnb EpollCreate(size int) (fd int, err error)
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64_64
|
||||
|
2
vendor/golang.org/x/sys/unix/syscall_linux_amd64.go
generated
vendored
2
vendor/golang.org/x/sys/unix/syscall_linux_amd64.go
generated
vendored
@ -6,7 +6,7 @@
|
||||
|
||||
package unix
|
||||
|
||||
//sys Dup2(oldfd int, newfd int) (err error)
|
||||
//sys dup2(oldfd int, newfd int) (err error)
|
||||
//sysnb EpollCreate(size int) (fd int, err error)
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
||||
|
2
vendor/golang.org/x/sys/unix/syscall_linux_arm.go
generated
vendored
2
vendor/golang.org/x/sys/unix/syscall_linux_arm.go
generated
vendored
@ -80,7 +80,7 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
|
||||
|
||||
// 64-bit file system and 32-bit uid calls
|
||||
// (16-bit uid calls are not always supported in newer kernels)
|
||||
//sys Dup2(oldfd int, newfd int) (err error)
|
||||
//sys dup2(oldfd int, newfd int) (err error)
|
||||
//sysnb EpollCreate(size int) (fd int, err error)
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32
|
||||
|
6
vendor/golang.org/x/sys/unix/syscall_linux_arm64.go
generated
vendored
6
vendor/golang.org/x/sys/unix/syscall_linux_arm64.go
generated
vendored
@ -210,9 +210,9 @@ func InotifyInit() (fd int, err error) {
|
||||
return InotifyInit1(0)
|
||||
}
|
||||
|
||||
func Dup2(oldfd int, newfd int) (err error) {
|
||||
return Dup3(oldfd, newfd, 0)
|
||||
}
|
||||
// dup2 exists because func Dup3 in syscall_linux.go references
|
||||
// it in an unreachable path. dup2 isn't available on arm64.
|
||||
func dup2(oldfd int, newfd int) error
|
||||
|
||||
func Pause() error {
|
||||
_, err := ppoll(nil, 0, nil, nil)
|
||||
|
2
vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go
generated
vendored
2
vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go
generated
vendored
@ -7,7 +7,7 @@
|
||||
|
||||
package unix
|
||||
|
||||
//sys Dup2(oldfd int, newfd int) (err error)
|
||||
//sys dup2(oldfd int, newfd int) (err error)
|
||||
//sysnb EpollCreate(size int) (fd int, err error)
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
||||
|
2
vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go
generated
vendored
2
vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go
generated
vendored
@ -14,7 +14,7 @@ import (
|
||||
|
||||
func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||
|
||||
//sys Dup2(oldfd int, newfd int) (err error)
|
||||
//sys dup2(oldfd int, newfd int) (err error)
|
||||
//sysnb EpollCreate(size int) (fd int, err error)
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
||||
|
2
vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go
generated
vendored
2
vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go
generated
vendored
@ -7,7 +7,7 @@
|
||||
|
||||
package unix
|
||||
|
||||
//sys Dup2(oldfd int, newfd int) (err error)
|
||||
//sys dup2(oldfd int, newfd int) (err error)
|
||||
//sysnb EpollCreate(size int) (fd int, err error)
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
||||
|
8
vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go
generated
vendored
8
vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go
generated
vendored
@ -191,10 +191,6 @@ func InotifyInit() (fd int, err error) {
|
||||
return InotifyInit1(0)
|
||||
}
|
||||
|
||||
func Dup2(oldfd int, newfd int) (err error) {
|
||||
return Dup3(oldfd, newfd, 0)
|
||||
}
|
||||
|
||||
func Pause() error {
|
||||
_, err := ppoll(nil, 0, nil, nil)
|
||||
return err
|
||||
@ -228,3 +224,7 @@ func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error
|
||||
}
|
||||
return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags)
|
||||
}
|
||||
|
||||
// dup2 exists because func Dup3 in syscall_linux.go references
|
||||
// it in an unreachable path. dup2 isn't available on arm64.
|
||||
func dup2(oldfd int, newfd int) error
|
||||
|
2
vendor/golang.org/x/sys/unix/syscall_linux_s390x.go
generated
vendored
2
vendor/golang.org/x/sys/unix/syscall_linux_s390x.go
generated
vendored
@ -10,7 +10,7 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//sys Dup2(oldfd int, newfd int) (err error)
|
||||
//sys dup2(oldfd int, newfd int) (err error)
|
||||
//sysnb EpollCreate(size int) (fd int, err error)
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
||||
|
2
vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go
generated
vendored
2
vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go
generated
vendored
@ -8,7 +8,7 @@ package unix
|
||||
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
||||
//sys Dup2(oldfd int, newfd int) (err error)
|
||||
//sys dup2(oldfd int, newfd int) (err error)
|
||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||
//sys Fstat(fd int, stat *Stat_t) (err error)
|
||||
//sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
|
||||
|
17
vendor/golang.org/x/sys/unix/syscall_unix.go
generated
vendored
17
vendor/golang.org/x/sys/unix/syscall_unix.go
generated
vendored
@ -12,6 +12,8 @@ import (
|
||||
"sync"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/internal/unsafeheader"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -113,15 +115,12 @@ func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (d
|
||||
return nil, errno
|
||||
}
|
||||
|
||||
// Slice memory layout
|
||||
var sl = struct {
|
||||
addr uintptr
|
||||
len int
|
||||
cap int
|
||||
}{addr, length, length}
|
||||
|
||||
// Use unsafe to turn sl into a []byte.
|
||||
b := *(*[]byte)(unsafe.Pointer(&sl))
|
||||
// Use unsafe to convert addr into a []byte.
|
||||
var b []byte
|
||||
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&b))
|
||||
hdr.Data = unsafe.Pointer(addr)
|
||||
hdr.Cap = length
|
||||
hdr.Len = length
|
||||
|
||||
// Register mapping in m and return it.
|
||||
p := &b[cap(b)-1]
|
||||
|
2
vendor/golang.org/x/sys/unix/zerrors_linux.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zerrors_linux.go
generated
vendored
@ -2165,6 +2165,8 @@ const (
|
||||
TCP_USER_TIMEOUT = 0x12
|
||||
TCP_WINDOW_CLAMP = 0xa
|
||||
TCP_ZEROCOPY_RECEIVE = 0x23
|
||||
TFD_TIMER_ABSTIME = 0x1
|
||||
TFD_TIMER_CANCEL_ON_SET = 0x2
|
||||
TIMER_ABSTIME = 0x1
|
||||
TIOCM_DTR = 0x2
|
||||
TIOCM_LE = 0x1
|
||||
|
2
vendor/golang.org/x/sys/unix/zerrors_linux_386.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zerrors_linux_386.go
generated
vendored
@ -342,6 +342,8 @@ const (
|
||||
TCSETXF = 0x5434
|
||||
TCSETXW = 0x5435
|
||||
TCXONC = 0x540a
|
||||
TFD_CLOEXEC = 0x80000
|
||||
TFD_NONBLOCK = 0x800
|
||||
TIOCCBRK = 0x5428
|
||||
TIOCCONS = 0x541d
|
||||
TIOCEXCL = 0x540c
|
||||
|
2
vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go
generated
vendored
@ -343,6 +343,8 @@ const (
|
||||
TCSETXF = 0x5434
|
||||
TCSETXW = 0x5435
|
||||
TCXONC = 0x540a
|
||||
TFD_CLOEXEC = 0x80000
|
||||
TFD_NONBLOCK = 0x800
|
||||
TIOCCBRK = 0x5428
|
||||
TIOCCONS = 0x541d
|
||||
TIOCEXCL = 0x540c
|
||||
|
2
vendor/golang.org/x/sys/unix/zerrors_linux_arm.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zerrors_linux_arm.go
generated
vendored
@ -349,6 +349,8 @@ const (
|
||||
TCSETXF = 0x5434
|
||||
TCSETXW = 0x5435
|
||||
TCXONC = 0x540a
|
||||
TFD_CLOEXEC = 0x80000
|
||||
TFD_NONBLOCK = 0x800
|
||||
TIOCCBRK = 0x5428
|
||||
TIOCCONS = 0x541d
|
||||
TIOCEXCL = 0x540c
|
||||
|
2
vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
generated
vendored
@ -336,6 +336,8 @@ const (
|
||||
TCSETXF = 0x5434
|
||||
TCSETXW = 0x5435
|
||||
TCXONC = 0x540a
|
||||
TFD_CLOEXEC = 0x80000
|
||||
TFD_NONBLOCK = 0x800
|
||||
TIOCCBRK = 0x5428
|
||||
TIOCCONS = 0x541d
|
||||
TIOCEXCL = 0x540c
|
||||
|
2
vendor/golang.org/x/sys/unix/zerrors_linux_mips.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zerrors_linux_mips.go
generated
vendored
@ -339,6 +339,8 @@ const (
|
||||
TCSETSW = 0x540f
|
||||
TCSETSW2 = 0x8030542c
|
||||
TCXONC = 0x5406
|
||||
TFD_CLOEXEC = 0x80000
|
||||
TFD_NONBLOCK = 0x80
|
||||
TIOCCBRK = 0x5428
|
||||
TIOCCONS = 0x80047478
|
||||
TIOCEXCL = 0x740d
|
||||
|
2
vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go
generated
vendored
@ -339,6 +339,8 @@ const (
|
||||
TCSETSW = 0x540f
|
||||
TCSETSW2 = 0x8030542c
|
||||
TCXONC = 0x5406
|
||||
TFD_CLOEXEC = 0x80000
|
||||
TFD_NONBLOCK = 0x80
|
||||
TIOCCBRK = 0x5428
|
||||
TIOCCONS = 0x80047478
|
||||
TIOCEXCL = 0x740d
|
||||
|
2
vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go
generated
vendored
@ -339,6 +339,8 @@ const (
|
||||
TCSETSW = 0x540f
|
||||
TCSETSW2 = 0x8030542c
|
||||
TCXONC = 0x5406
|
||||
TFD_CLOEXEC = 0x80000
|
||||
TFD_NONBLOCK = 0x80
|
||||
TIOCCBRK = 0x5428
|
||||
TIOCCONS = 0x80047478
|
||||
TIOCEXCL = 0x740d
|
||||
|
2
vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go
generated
vendored
@ -339,6 +339,8 @@ const (
|
||||
TCSETSW = 0x540f
|
||||
TCSETSW2 = 0x8030542c
|
||||
TCXONC = 0x5406
|
||||
TFD_CLOEXEC = 0x80000
|
||||
TFD_NONBLOCK = 0x80
|
||||
TIOCCBRK = 0x5428
|
||||
TIOCCONS = 0x80047478
|
||||
TIOCEXCL = 0x740d
|
||||
|
2
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go
generated
vendored
@ -393,6 +393,8 @@ const (
|
||||
TCSETSF = 0x802c7416
|
||||
TCSETSW = 0x802c7415
|
||||
TCXONC = 0x2000741e
|
||||
TFD_CLOEXEC = 0x80000
|
||||
TFD_NONBLOCK = 0x800
|
||||
TIOCCBRK = 0x5428
|
||||
TIOCCONS = 0x541d
|
||||
TIOCEXCL = 0x540c
|
||||
|
2
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go
generated
vendored
@ -393,6 +393,8 @@ const (
|
||||
TCSETSF = 0x802c7416
|
||||
TCSETSW = 0x802c7415
|
||||
TCXONC = 0x2000741e
|
||||
TFD_CLOEXEC = 0x80000
|
||||
TFD_NONBLOCK = 0x800
|
||||
TIOCCBRK = 0x5428
|
||||
TIOCCONS = 0x541d
|
||||
TIOCEXCL = 0x540c
|
||||
|
2
vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go
generated
vendored
@ -330,6 +330,8 @@ const (
|
||||
TCSETXF = 0x5434
|
||||
TCSETXW = 0x5435
|
||||
TCXONC = 0x540a
|
||||
TFD_CLOEXEC = 0x80000
|
||||
TFD_NONBLOCK = 0x800
|
||||
TIOCCBRK = 0x5428
|
||||
TIOCCONS = 0x541d
|
||||
TIOCEXCL = 0x540c
|
||||
|
2
vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go
generated
vendored
@ -403,6 +403,8 @@ const (
|
||||
TCSETXF = 0x5434
|
||||
TCSETXW = 0x5435
|
||||
TCXONC = 0x540a
|
||||
TFD_CLOEXEC = 0x80000
|
||||
TFD_NONBLOCK = 0x800
|
||||
TIOCCBRK = 0x5428
|
||||
TIOCCONS = 0x541d
|
||||
TIOCEXCL = 0x540c
|
||||
|
2
vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go
generated
vendored
@ -392,6 +392,8 @@ const (
|
||||
TCSETSW = 0x8024540a
|
||||
TCSETSW2 = 0x802c540e
|
||||
TCXONC = 0x20005406
|
||||
TFD_CLOEXEC = 0x400000
|
||||
TFD_NONBLOCK = 0x4000
|
||||
TIOCCBRK = 0x2000747a
|
||||
TIOCCONS = 0x20007424
|
||||
TIOCEXCL = 0x2000740d
|
||||
|
31
vendor/golang.org/x/sys/unix/zsyscall_linux.go
generated
vendored
31
vendor/golang.org/x/sys/unix/zsyscall_linux.go
generated
vendored
@ -1450,6 +1450,37 @@ func Sysinfo(info *Sysinfo_t) (err error) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func TimerfdCreate(clockid int, flags int) (fd int, err error) {
|
||||
r0, _, e1 := RawSyscall(SYS_TIMERFD_CREATE, uintptr(clockid), uintptr(flags), 0)
|
||||
fd = int(r0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func TimerfdGettime(fd int, currValue *ItimerSpec) (err error) {
|
||||
_, _, e1 := RawSyscall(SYS_TIMERFD_GETTIME, uintptr(fd), uintptr(unsafe.Pointer(currValue)), 0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func TimerfdSettime(fd int, flags int, newValue *ItimerSpec, oldValue *ItimerSpec) (err error) {
|
||||
_, _, e1 := RawSyscall6(SYS_TIMERFD_SETTIME, uintptr(fd), uintptr(flags), uintptr(unsafe.Pointer(newValue)), uintptr(unsafe.Pointer(oldValue)), 0, 0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Tgkill(tgid int, tid int, sig syscall.Signal) (err error) {
|
||||
_, _, e1 := RawSyscall(SYS_TGKILL, uintptr(tgid), uintptr(tid), uintptr(sig))
|
||||
if e1 != 0 {
|
||||
|
2
vendor/golang.org/x/sys/unix/zsyscall_linux_386.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zsyscall_linux_386.go
generated
vendored
@ -55,7 +55,7 @@ func pipe(p *[2]_C_int) (err error) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Dup2(oldfd int, newfd int) (err error) {
|
||||
func dup2(oldfd int, newfd int) (err error) {
|
||||
_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
|
2
vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go
generated
vendored
@ -45,7 +45,7 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Dup2(oldfd int, newfd int) (err error) {
|
||||
func dup2(oldfd int, newfd int) (err error) {
|
||||
_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
|
2
vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go
generated
vendored
@ -234,7 +234,7 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Dup2(oldfd int, newfd int) (err error) {
|
||||
func dup2(oldfd int, newfd int) (err error) {
|
||||
_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
|
2
vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go
generated
vendored
@ -45,7 +45,7 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Dup2(oldfd int, newfd int) (err error) {
|
||||
func dup2(oldfd int, newfd int) (err error) {
|
||||
_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
|
2
vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go
generated
vendored
@ -45,7 +45,7 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Dup2(oldfd int, newfd int) (err error) {
|
||||
func dup2(oldfd int, newfd int) (err error) {
|
||||
_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
|
2
vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go
generated
vendored
@ -45,7 +45,7 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Dup2(oldfd int, newfd int) (err error) {
|
||||
func dup2(oldfd int, newfd int) (err error) {
|
||||
_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
|
2
vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go
generated
vendored
@ -45,7 +45,7 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Dup2(oldfd int, newfd int) (err error) {
|
||||
func dup2(oldfd int, newfd int) (err error) {
|
||||
_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
|
2
vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go
generated
vendored
@ -45,7 +45,7 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Dup2(oldfd int, newfd int) (err error) {
|
||||
func dup2(oldfd int, newfd int) (err error) {
|
||||
_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
|
2
vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go
generated
vendored
@ -45,7 +45,7 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Dup2(oldfd int, newfd int) (err error) {
|
||||
func dup2(oldfd int, newfd int) (err error) {
|
||||
_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
|
2
vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go
generated
vendored
2
vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go
generated
vendored
@ -45,7 +45,7 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Dup2(oldfd int, newfd int) (err error) {
|
||||
func dup2(oldfd int, newfd int) (err error) {
|
||||
_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user